gym 102059A 树链剖分后odt维护区间

题意

一棵树

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

题解:

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

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

代码:

#include<bits/stdc++.h>
#define endl '\n'
#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;
}

 

posted @ 2019-04-02 13:28  nervending  阅读(251)  评论(0编辑  收藏  举报