zoukankan      html  css  js  c++  java
  • gym 102059A 树链剖分后odt维护区间

    题意

    一棵树

    多次修改,每次修改一个点到根的所有边的颜色,并询问现在有哪些颜色染了恰好$m$条边

    题解:

    稍加思考可以知道,从某个点到根节点的颜色数,均摊复杂度很低,因此,可以考虑珂朵莉树维护重链剖分

    这里也记录一下珂朵莉树的代码

    代码:

    #include<bits/stdc++.h>
    #define endl '
    '
    #define ll long long
    #define ull unsigned long long
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define all(x) x.begin(),x.end()
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    #define per(ii,a,b) for(int ii=b;ii>=a;--ii)
    #define forn(ii,x) for(int ii=head[x];ii;ii=edge[ii].next)
    using namespace std;
    const int maxn=2e5+20,maxm=2e6+10;
    const int INF=0x3f3f3f3f;
    const ll mod=1e9+7;
    int casn,n,m,k,col[maxn],ans[maxn];
    class odtree{public:
      struct segnode{int l,r,c;bool operator <(const segnode &a)const{return r<a.r;}};
      set<segnode> nodes;
      void split(int pos){auto it=nodes.lower_bound({pos,pos});
        if(it==nodes.end()||(it->l)>pos||(it->r)==pos) return ;
        int l=it->l,r=it->r,c=it->c;
        nodes.erase(it);nodes.insert({l,pos,c});nodes.insert({pos+1,r,c});
      }
      void update(int l,int r,int c){
        split(l-1);split(r);
        while(1){auto it=nodes.lower_bound({l,l});
          if(it==nodes.end()||(it->l)>r)  break;
          if(it->c){--ans[col[it->c]];col[it->c]-=(it->r)-(it->l)+1;++ans[col[it->c]];}
          nodes.erase(it);
        }
        --ans[col[c]];col[c]+=r-l+1;++ans[col[c]];
        nodes.insert({l,r,c});
      }
    }tree;
    namespace chain{
      struct data_e{int to,next;}edge[maxn<<1];
      int head[maxn],nume,mp[maxn];
      int ltop[maxn],fa[maxn],deep[maxn];
      int sz[maxn],remp[maxn],son[maxn],cnt;
      inline void addedge(int a,int b){edge[++nume]={b,head[a]};head[a]=nume;}
      void init(){rep(i,1,n) head[i]=0;cnt=nume=0;}
      void dfs1(int now,int pre,int d){
        deep[now]=d,fa[now]=pre,sz[now]=1,son[now]=0;
        forn(i,now){int to=edge[i].to;
          if(to!=pre) {
            dfs1(to,now,d+1);sz[now]+=sz[to];
            if(sz[to]>sz[son[now]]) son[now]=to;
          }
        }
      }
      void dfs2(int now,int pre,int sp){
        ltop[now]=sp;mp[now]=++cnt;remp[cnt]=now;
        if(son[now])  dfs2(son[now],now,sp);
        forn(i,now){int to=edge[i].to;
          if(to!=son[now]&&to!=pre) dfs2(to,now,to);
        }
      }
      void gao(int st=1){dfs1(st,0,0);dfs2(st,0,st);}
      void update(int now,int c){
        while(now>1){
          int l=max(mp[ltop[now]],2),r=mp[now];
          if(l<=r) tree.update(l,r,c);
          now=fa[ltop[now]];
        }
      }
    };
    int main() {IO;
      cin>>n>>m>>k;
      rep(i,1,n-1){int a,b;
        cin>>a>>b;
        chain::addedge(a,b);chain::addedge(b,a);
      }
      ans[0]=m;
      chain::gao();
      tree.nodes.insert({2,n,0});
      while(k--){int a,b,c;
        cin>>a>>b>>c;
        chain::update(a,b);
        cout<<ans[c]<<endl;
      }
      return 0;
    }
    
  • 相关阅读:
    系统设计的一些原则
    分层开发思想与小笼包
    工作与生活
    Microsoft .NET Pet Shop 4 架构与技术分析
    用人之道(二) 如何管理软件开发团队
    也谈很多开发人员的毛病
    《3S新闻周刊》第10期,本期策划:“超女”营销带来的启示
    浅析ArcIMS
    MapX的坐标问题
    应用ArcIMS构建GMap风格的地图应用
  • 原文地址:https://www.cnblogs.com/nervendnig/p/10642087.html
Copyright © 2011-2022 走看看