[SDOI2014]旅行
题解:
这题一看就知道要么是树剖要么是lct
仔细分析一下
要是对每个颜色维护一下
插入和删除就相当于对一个的权值进行改变(删除就是变成0)
问题是空间不够了
那就树剖搞动态开点 问题就解决了
对于lct,可以把颜色分开来离线搞
但是对于这道题显然树剖比较有优势
因为lct细节挺多的。。
比如当一个点修改时会对后继这个点的所有颜色有影响要记录
复原的时候lct的树不用动他就把修改过的那些权值赋0就好了(拿队列记录一下)
以后有空再写lct的
下面是树剖的代码
太久没写过主席树调出好多错:
#include <bits/stdc++.h> using namespace std; const int N=2e6+100; int fa[N],son[N],dep[N],size[N],root[N],head[N]; int c[N],w[N],id[N],real2[N],num,l,top[N]; int leftson[N],rightson[N],cnt,n,m; struct re{ int a,b; }a[N*2]; void arr(int x,int y) { a[++l].a=head[x]; a[l].b=y; head[x]=l; } void dfs1(int x,int y) { fa[x]=y; dep[x]=dep[y]+1; son[x]=-1; size[x]=1; int u=head[x]; while (u) { int v=a[u].b; if (v!=y) { dfs1(v,x); size[x]+=size[v]; if (size[son[x]]<size[v]) son[x]=v; } u=a[u].a; } } void dfs2(int x,int y) { top[x]=y; num++; id[x]=num; real2[num]=x; if (son[x]==-1) return; dfs2(son[x],y); int u=head[x]; while (u) { int v=a[u].b; if (v!=fa[x]&&v!=son[x]) dfs2(v,v); u=a[u].a; } } struct ree{ int h,t,sum,maxn; }p[10000000]; #define mid (h+t)/2 void updata(int x) { p[x].sum=p[leftson[x]].sum+p[rightson[x]].sum; p[x].maxn=max(p[leftson[x]].maxn,p[rightson[x]].maxn); } void change(int &x,int h,int t,int pos,int w) { if (x==0) x=++cnt; if (h==t) { p[x].sum=w; p[x].maxn=w; return; } if (pos<=mid) change(leftson[x],h,mid,pos,w); else change(rightson[x],mid+1,t,pos,w); updata(x); } int query1(int x,int h,int t,int posh,int post) { if (x==0||posh>t||post<h) return(0); if (posh<=h&&t<=post) { return(p[x].sum); } return(query1(leftson[x],h,mid,posh,post)+query1(rightson[x],mid+1,t,posh,post)); } int query2(int x,int h,int t,int posh,int post) { if (x==0||posh>t||post<h) return(0); if (posh<=h&&t<=post) { return(p[x].maxn); } return(max(query2(leftson[x],h,mid,posh,post),query2(rightson[x],mid+1,t,posh,post))); } int query1x(int col,int x,int y) { int ans=0,f1=top[x],f2=top[y]; while (f1!=f2) { if (dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); ans+=query1(root[col],1,n,id[f1],id[x]); x=fa[f1]; f1=top[x]; } if (dep[x]<dep[y]) swap(x,y); ans+=query1(root[col],1,n,id[y],id[x]); return(ans); } int query2x(int col,int x,int y) { int ans=0,f1=top[x],f2=top[y]; while (f1!=f2) { if (dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); ans=max(ans,query2(root[col],1,n,id[f1],id[x])); x=fa[f1]; f1=top[x]; } if (dep[x]<dep[y]) swap(x,y); ans=max(ans,query2(root[col],1,n,id[y],id[x])); return(ans); } int main() { cin>>n>>m; for (int i=1;i<=n;i++) cin>>w[i]>>c[i]; int cc,dd; for (int i=1;i<=n-1;i++) { cin>>cc>>dd; arr(cc,dd); arr(dd,cc); } dfs1(1,0); dfs2(1,1); for (int i=1;i<=n;i++) change(root[c[i]],1,n,id[i],w[i]); for (int i=1;i<=m;i++) { char cc0,cc1; int x,y; cin>>cc0>>cc1>>x>>y; if (cc0=='Q'&&cc1=='S') { cout<<query1x(c[x],x,y)<<endl; } if (cc0=='C'&&cc1=='W') { w[x]=y; change(root[c[x]],1,n,id[x],y); } if (cc0=='C'&&cc1=='C') { change(root[c[x]],1,n,id[x],0); c[x]=y; change(root[y],1,n,id[x],w[x]); } if (cc0=='Q'&&cc1=='M') { cout<<query2x(c[x],x,y)<<endl; } } return 0; }