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; }