树上连通块
不用具体距离,只询问连通块大小或者最大权值
可以类比Qtree5的方法,但是记录东西很多,例如子树有无0/1颜色等
一个trick,两个LCT分离颜色
每个颜色在边上。
仅保留连通块顶部不是相同颜色,使得断边不会被菊花图卡掉
所以内部颜色不用考虑了,专心维护子树值。
查询时候findrt,splay,右儿子即可。
Qtree6
#include<bits/stdc++.h> #define reg register int #define il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^'0') using namespace std; typedef long long ll; template<class T>il void rd(T &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');} template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');} template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar(' ');} namespace Miracle{ const int N=1000000+5; int n,m; int f[N]; int co[N]; struct LCT{ #define ls ch[x][0] #define rs ch[x][1] int fa[N],ch[N][2]; int sz[N],si[N]; bool nrt(int x){ return ch[fa[x]][0]==x||ch[fa[x]][1]==x; } void pushup(int x){ if(x) sz[x]=si[x]+sz[ls]+sz[rs]+1; } void rotate(int x){ int y=fa[x],d=ch[y][1]==x; fa[ch[y][d]=ch[x][!d]]=y; if(nrt(y)) ch[fa[x]=fa[y]][ch[fa[y]][1]==y]=x; else fa[x]=fa[y]; fa[ch[x][!d]=y]=x; pushup(y); } void splay(int x){ while(nrt(x)){ int y=fa[x],z=fa[y]; if(nrt(y)){ rotate((ch[y][0]==x)==(ch[z][0]==y)?y:x); } rotate(x); } pushup(x); } void access(int x){ for(reg y=0;x;y=x,x=fa[x]){ //cout<<" xx "<<x<<endl; splay(x);si[x]-=sz[y];si[x]+=sz[ch[x][1]]; ch[x][1]=y; pushup(x); } } int findrt(int x){ access(x);splay(x); while(ch[x][0]) x=ch[x][0]; splay(x); return x; } void link(int x){ //cout<<" link "<<x<<endl; splay(x); int y=fa[x]=f[x]; access(y);splay(y); si[y]+=sz[x]; pushup(y); } void cut(int x){ // cout<<" cut "<<x<<endl; access(x);splay(x); // cout<<ls<<" "<<ch[x][0]<<endl; ls=fa[ls]=0; pushup(x); } int query(int x){ int lp=findrt(x); // cout<<" lp "<<lp<<" "<<sz[lp]<<" "<<si[lp]<<endl; return sz[lp]-si[lp]-1; } }lct[2]; vector<int>to[N]; void dfs(int x){ for(reg i=0;i<(int)to[x].size();++i){ if(to[x][i]!=f[x]){ f[to[x][i]]=x;dfs(to[x][i]); lct[1].link(to[x][i]); } } } int main(){ rd(n); int x,y; for(reg i=1;i<n;++i)rd(x),rd(y),to[x].push_back(y),to[y].push_back(x); for(reg i=1;i<=n+1;++i) lct[0].sz[i]=1,lct[1].sz[i]=1,co[i]=1; to[n+1].push_back(1); dfs(n+1); int op; rd(m); while(m--){ rd(op);rd(x); if(!op){ printf("%d ",lct[co[x]].query(x)); }else{ lct[co[x]].cut(x); // cout<<" after co[x] cut "<<endl; lct[co[x]^1].link(x); co[x]^=1; } } return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/3/15 10:57:40 */
Qtree7
#include<bits/stdc++.h> #define reg register int #define il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^'0') using namespace std; typedef long long ll; template<class T>il void rd(T &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');} template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');} template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar(' ');} namespace Miracle{ const int N=1e5+5; const int inf=0x3f3f3f3f; int n,m; int fa[N]; struct LCT{ struct node{ int ch[2],fa; int val; int ans; priority_queue<int>q,d; void dele(int c){ d.push(c); } void ins(int c){ q.push(c); } int top(){ while(!q.empty()&&!d.empty()&&q.top()==d.top()) q.pop(),d.pop(); if(!q.empty()) return q.top(); return -inf; } }t[N]; bool nrt(int x){ return t[t[x].fa].ch[0]==x||t[t[x].fa].ch[1]==x; } void pushup(int x){ t[x].ans=max(t[x].val,max(t[x].top(),max(t[t[x].ch[0]].ans,t[t[x].ch[1]].ans))); } void rotate(int x){ int y=t[x].fa,d=t[y].ch[1]==x; t[t[y].ch[d]=t[x].ch[!d]].fa=y; if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[1]==y]=x; else t[x].fa=t[y].fa; t[t[x].ch[!d]=y].fa=x; pushup(y); } void splay(int x){ while(nrt(x)){ int y=t[x].fa,z=t[y].fa; if(nrt(y)){ rotate((t[y].ch[1]==x)==(t[z].ch[1]==y)?y:x); }rotate(x); } pushup(x); } void access(int x){ for(reg y=0;x;y=x,x=t[x].fa){ splay(x);t[x].dele(t[y].ans); t[x].ins(t[t[x].ch[1]].ans); t[x].ch[1]=y; pushup(x); } } int findrt(int x){ access(x);splay(x); while(t[x].ch[0]) x=t[x].ch[0]; splay(x); return x; } void link(int x){ // cout<<" link "<<x<<" t.fa "<<t[x].fa<<" fa "<<fa[x]<<" ans "<<t[x].ans<<" val "<<t[x].val<<endl; splay(x); int y=t[x].fa=fa[x]; access(y);splay(y); t[y].ins(t[x].ans); pushup(y); } void cut(int x){ access(x);splay(x); t[x].ch[0]=t[t[x].ch[0]].fa=0; pushup(x); } void chan(int x,int c){//chan val access(x);splay(x); t[x].val=c; pushup(x); } int query(int x){ int lp=findrt(x); return t[t[lp].ch[1]].ans; } }lct[2]; vector<int>to[N]; int co[N],wei[N]; void dfs(int x){ //cout<<x<<endl; for(reg i=0;i<(int)to[x].size();++i){ int y=to[x][i]; if(y==fa[x]) continue; fa[y]=x; dfs(y); lct[co[y]].link(y); } } int main(){ rd(n); lct[0].t[0].ans=lct[0].t[0].val=-inf; lct[1].t[0].ans=lct[1].t[0].val=-inf; lct[0].t[n+1].ans=lct[0].t[n+1].val=-inf; lct[1].t[n+1].ans=lct[1].t[n+1].val=-inf; int x,y; for(reg i=1;i<n;++i){ rd(x);rd(y); to[x].push_back(y);to[y].push_back(x); } to[n+1].push_back(1); for(reg i=1;i<=n;++i){ rd(co[i]); } for(reg i=1;i<=n;++i){ rd(wei[i]); // cout<<" i "<<i<<" "<<wei[i]<<endl; lct[0].t[i].val=lct[0].t[i].ans=wei[i]; lct[1].t[i].val=lct[1].t[i].ans=wei[i]; } wei[n+1]=-inf; dfs(n+1); rd(m);int op; while(m--){ rd(op);rd(x); if(op==0){ printf("%d ",lct[co[x]].query(x)); }else if(op==1){ lct[co[x]].cut(x);lct[co[x]^1].link(x); co[x]^=1; }else{ rd(y); lct[0].chan(x,y); lct[1].chan(x,y); } } return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/3/15 14:12:29 */