【Learning】Link-Cut Tree 题目汇总
2017-12-05 19:44
417 查看
这篇博客主要是记录了我Link-Cut Tree的做题记录。
推荐一个非常好的博客。orz DTZ学长 %%%%%%%
http://www.cnblogs.com/RogerDTZ/p/7436469.html
T1 bzoj2049
T2 bzoj2002
T3 bzoj2631
T4 bzoj4530
[b]T5 bzoj2843&&bzoj1180
T6 hdu4010
T7 bzoj3282
T8 bzoj3669
T8 bzoj3306
和遥远的国度一题很像,只不过写了Link-Cut Tree。打了一个Treap。
T9 bzoj2959
T10 bzoj2594
T11 uva11994
各种乱搞之后终于过了!仍然把边变成点。
其实我的代码判断祖孙关系非常暴力,可以被卡。暂时没想到怎么在动态树中快速判断祖孙关系==
推荐一个非常好的博客。orz DTZ学长 %%%%%%%
http://www.cnblogs.com/RogerDTZ/p/7436469.html
T1 bzoj2049
#include<cstdio> #include<algorithm> using namespace std; int n,m,u,v,fa[10005],ch[10005][2]; char s[20]; bool rev[10005]; bool isroot(int u){ return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u; } int which(int u){ return ch[fa[u]][1]==u; } void reverse(int u){ rev[u]^=1; swap(ch[u][0],ch[u][1]); } void downtag(int u){ if(rev[u]){ if(ch[u][0]){ reverse(ch[u][0]); } if(ch[u][1]){ reverse(ch[u][1]); } rev[u]=0; } } void pushdown(int u){ if(!isroot(u)){ pushdown(fa[u]); } downtag(u); } void rotate(int x){ int y=fa[x],z=fa[y],md=which(x); if(!isroot(y)){ ch[z][which(y)]=x; } fa[x]=z; ch[y][md]=ch[x][!md]; fa[ch[y][md]]=y; ch[x][!md]=y; fa[y]=x; } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u])){ rotate(which(fa[u])==which(u)?fa[u]:u); } rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); ch[u][1]=v; } } void makeroot(int u){ access(u); splay(u); reverse(u); } void link(int u,int v){ makeroot(u); fa[u]=v; } void cut(int u,int v){ makeroot(u); access(v); splay(v); fa[u]=0; ch[v][0]=0; } bool isconnect(int u,int v){ if(u==v){ return true; } makeroot(u); access(v); splay(v); return fa[u]!=0; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%s%d%d",s,&u,&v); if(s[0]=='C'){ link(u,v); }else if(s[0]=='D'){ cut(u,v); }else{ if(isconnect(u,v)){ puts("Yes"); }else{ puts("No"); } } } return 0; }
T2 bzoj2002
#include<cstdio> #include<algorithm> using namespace std; const int N=200005; int n,m,op,x,y,a ,ch [2],fa ,siz ,rev ; bool isroot(int u){ return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u; } int which(int u){ return u==ch[fa[u]][1]; } void pushup(int u){ siz[u]=1; if(ch[u][0]){ siz[u]+=siz[ch[u][0]]; } if(ch[u][1]){ siz[u]+=siz[ch[u][1]]; } } void reverse(int u){ rev[u]^=1; swap(ch[u][0],ch[u][1]); } void downtag(int u){ if(rev[u]){ if(ch[u][0]){ reverse(ch[u][0]); } if(ch[u][1]){ reverse(ch[u][1]); } rev[u]=0; } } void pushdown(int u){ if(!isroot(u)){ pushdown(fa[u]); } downtag(u); } void rotate(int x){ int y=fa[x],z=fa[y],md=which(x); if(!isroot(y)){ ch[z][which(y)]=x; } fa[x]=z; ch[y][md]=ch[x][!md]; fa[ch[y][md]]=y; ch[x][!md]=y; fa[y]=x; pushup(y); pushup(x); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u])){ rotate(which(fa[u])==which(u)?fa[u]:u); } rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); ch[u][1]=v; pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } void link(int u,int v){ makeroot(u); fa[u]=v; } void cut(int u,int v){ makeroot(u); access(v); splay(v); fa[u]=ch[v][0]=0; pushup(v); } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); if(i+a[i]<=n){ a[i]=i+a[i]; }else{ a[i]=n+1; } link(i,a[i]); } scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d%d",&op,&x); x++; if(op==1){ makeroot(n+1); access(x); splay(x); printf("%d\n",siz[ch[x][0]]); }else{ scanf("%d",&y); cut(x,a[x]); if(x+y<=n){ a[x]=x+y; }else{ a[x]=n+1; } link(x,a[x]); } } return 0; }
T3 bzoj2631
#include<cstdio> #include<algorithm> using namespace std; typedef unsigned int ui; const int N=100005; const ui mod=51061; int n,q,u,v,u2,v2,c,rev ,fa ,ch [2],siz ; ui val ,sumv ,mulv ,addv ; char s[5]; bool isroot(int u){ return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u; } int which(int u){ return ch[fa[u]][1]==u; } void pushup(int u){ sumv[u]=val[u]; siz[u]=1; if(ch[u][0]){ sumv[u]=(sumv[u]+sumv[ch[u][0]])%mod; siz[u]+=siz[ch[u][0]]; } if(ch[u][1]){ sumv[u]=(sumv[u]+sumv[ch[u][1]])%mod; siz[u]+=siz[ch[u][1]]; } } void reverse(int u){ rev[u]^=1; swap(ch[u][0],ch[u][1]); } void maintain(int u,ui mul,ui add){ addv[u]=(addv[u]*mul%mod+add)%mod; mulv[u]=mulv[u]*mul%mod; val[u]=(val[u]*mul%mod+add)%mod; sumv[u]=(sumv[u]*mul%mod+siz[u]*add%mod)%mod; } void downtag(int u){ if(mulv[u]!=1||addv[u]){ if(ch[u][0]){ maintain(ch[u][0],mulv[u],addv[u]); } if(ch[u][1]){ maintain(ch[u][1],mulv[u],addv[u]); } mulv[u]=1; addv[u]=0; } if(rev[u]){ if(ch[u][0]){ reverse(ch[u][0]); } if(ch[u][1]){ reverse(ch[u][1]); } rev[u]=0; } } void pushdown(int u){ if(!isroot(u)){ pushdown(fa[u]); } downtag(u); } void rotate(int x){ int y=fa[x],z=fa[y],md=which(x); if(!isroot(y)){ ch[z][which(y)]=x; } fa[x]=z; ch[y][md]=ch[x][!md]; fa[ch[y][md]]=y; ch[x][!md]=y; fa[y]=x; pushup(y); pushup(x); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u])){ rotate(which(fa[u])==which(u)?fa[u]:u); } rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); ch[u][1]=v; pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } void link(int u,int v){ makeroot(u); fa[u]=v; } void cut(int u,int v){ makeroot(u); access(v); splay(v); fa[u]=ch[v][0]=0; pushup(v); } main(){ scanf("%d%d",&n,&q); for(int i=1;i<=n;i++){ val[i]=sumv[i]=mulv[i]=1; } for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); link(u,v); } for(int i=1;i<=q;i++){ scanf("%s%d%d",s,&u,&v); if(s[0]=='+'){ scanf("%d",&c); makeroot(u); access(v); splay(v); maintain(v,1,c); }else if(s[0]=='-'){ scanf("%d%d",&u2,&v2); cut(u,v); link(u2,v2); }else if(s[0]=='*'){ scanf("%d",&c); makeroot(u); access(v); splay(v); maintain(v,c,0); }else{ makeroot(u); access(v); splay(v); printf("%u\n",sumv[v]); } } return 0; }
T4 bzoj4530
#include<cstdio> #include<algorithm> using namespace std; const int N=100005; int n,q,u,v,ch [2],fa ,siz ,sx ,rev ; char s[10]; bool isroot(int u){ return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u; } int which(int u){ return u==ch[fa[u]][1]; } void pushup(int u){ siz[u]=sx[u]+1; if(ch[u][0]){ siz[u]+=siz[ch[u][0]]; } if(ch[u][1]){ siz[u]+=siz[ch[u][1]]; } } void reverse(int u){ rev[u]^=1; swap(ch[u][0],ch[u][1]); } void downtag(int u){ if(rev[u]){ if(ch[u][0]){ reverse(ch[u][0]); } if(ch[u][1]){ reverse(ch[u][1]); } rev[u]=0; } } void pushdown(int u){ if(!isroot(u)){ pushdown(fa[u]); } downtag(u); } void rotate(int x){ int y=fa[x],z=fa[y],md=which(x); if(!isroot(y)){ ch[z][which(y)]=x; } fa[x]=z; ch[y][md]=ch[x][!md]; fa[ch[y][md]]=y; ch[x][!md]=y; fa[y]=x; pushup(y); pushup(x); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u])){ rotate(which(fa[u])==which(u)?fa[u]:u); } rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); sx[u]+=siz[ch[u][1]]-siz[v]; ch[u][1]=v; pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } void link(int u,int v){ makeroot(u); makeroot(v); fa[u]=v; sx[v]+=siz[u]; pushup(v); } int main(){ scanf("%d%d",&n,&q); for(int i=1;i<=q;i++){ scanf("%s%d%d",s,&u,&v); if(s[0]=='A'){ link(u,v); }else{ makeroot(u); access(v); splay(v); printf("%lld\n",(long long)(siz[u])*(siz[v]-siz[u])); } } return 0; }
[b]T5 bzoj2843&&bzoj1180
#include<cstdio> #include<algorithm> using namespace std; const int N=30005; int n,m,u,v,fa ,val ,siz ,sumv ,rev ,ch [2]; char s[20]; bool isroot(int u){ return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u; } int which(int u){ return u==ch[fa[u]][1]; } void pushup(int u){ sumv[u]=val[u]; siz[u]=1; if(ch[u][0]){ sumv[u]+=sumv[ch[u][0]]; siz[u]+=siz[ch[u][0]]; } if(ch[u][1]){ sumv[u]+=sumv[ch[u][1]]; siz[u]+=siz[ch[u][1]]; } } void reverse(int u){ rev[u]^=1; swap(ch[u][0],ch[u][1]); } void downtag(int u){ if(rev[u]){ if(ch[u][0]){ reverse(ch[u][0]); } if(ch[u][1]){ reverse(ch[u][1]); } rev[u]=0; } } void pushdown(int u){ if(!isroot(u)){ pushdown(fa[u]); } downtag(u); } void rotate(int x){ int y=fa[x],z=fa[y],md=which(x); if(!isroot(y)){ ch[z][which(y)]=x; } fa[x]=z; ch[y][md]=ch[x][!md]; fa[ch[y][md]]=y; ch[x][!md]=y; fa[y]=x; pushup(y); pushup(x); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u])){ rotate(which(fa[u])==which(u)?fa[u]:u); } rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); ch[u][1]=v; pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } void link(int u,int v){ makeroot(u); fa[u]=v; } bool isconnect(int u,int v){ if(u==v){ return true; } makeroot(u); access(v); splay(v); return fa[u]!=0; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&val[i]); } scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%s%d%d",s,&u,&v); if(s[0]=='b'){ if(isconnect(u,v)){ puts("no"); }else{ puts("yes"); link(u,v); } }else if(s[0]=='p'){ makeroot(u); val[u]=v; pushup(u); }else{ if(isconnect(u,v)){ makeroot(u); access(v); splay(v); printf("%d\n",sumv[v]); }else{ puts("impossible"); } } } return 0; }
T6 hdu4010
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=300005; int n,q,u,v,w,op,cnt,fa ,ch [2],val ,rev ,maxv ,tag ; int uu ,vv ; void init(){ memset(fa,0,sizeof(fa)); memset(ch,0,sizeof(ch)); memset(val,0,sizeof(val)); memset(rev,0,sizeof(rev)); memset(maxv,0,sizeof(maxv)); memset(tag,0,sizeof(tag)); cnt=0; } bool isroot(int u){ return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u; } int which(int u){ return u==ch[fa[u]][1]; } void pushup(int u){ maxv[u]=max(val[u],max(maxv[ch[u][0]],maxv[ch[u][1]])); } void reverse(int u){ if(!u){ return; } rev[u]^=1; swap(ch[u][0],ch[u][1]); } void maintain(int u,int add){ if(!u){ return; } val[u]+=add; maxv[u]+=add; tag[u]+=add; } void downtag(int u){ if(rev[u]){ reverse(ch[u][0]); reverse(ch[u][1]); rev[u]=0; } if(tag[u]){ maintain(ch[u][0],tag[u]); maintain(ch[u][1],tag[u]); tag[u]=0; } } void pushdown(int u){ if(!isroot(u)){ pushdown(fa[u]); } downtag(u); } void rotate(int x){ int y=fa[x],z=fa[y],md=which(x); if(!isroot(y)){ ch[z][which(y)]=x; } fa[x]=z; ch[y][md]=ch[x][!md]; fa[ch[y][md]]=y; ch[x][!md]=y; fa[y]=x; pushup(y); pushup(x); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u])){ rotate(which(fa[u])==which(u)?fa[u]:u); } rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); ch[u][1]=v; pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } void link(int u,int v){ if(u==v){ return; } makeroot(u); fa[u]=v; if(u==v){ exit(0); } } void cut(int u,int v){ if(u==v){ return; } makeroot(u); access(v); splay(v); fa[u]=ch[v][0]=0; pushup(v); } bool isconnect(int u,int v){ if(u==v){ return true; } makeroot(u); access(v); splay(v); return fa[u]!=0; } int main(){ while(~scanf("%d",&n)){ init(); for(int i=1;i<n;i++){ scanf("%d%d",&uu[i],&vv[i]); } for(int i=1;i<=n;i++){ scanf("%d",&val[i]); maxv[i]=val[i]; } for(int i=1;i<n;i++){ link(uu[i],vv[i]); } scanf("%d",&q); for(int i=1;i<=q;i++){ scanf("%d",&op); if(op==1){ scanf("%d%d",&u,&v); if(isconnect(u,v)){ puts("-1"); }else{ link(u,v); } }else if(op==2){ scanf("%d%d",&u,&v); if(!isconnect(u,v)||u==v){ puts("-1"); }else{ cut(u,v); } }else if(op==3){ scanf("%d%d%d",&w,&u,&v); if(!isconnect(u,v)){ puts("-1"); }else{ makeroot(u); access(v); splay(v); maintain(v,w); } }else{ scanf("%d%d",&u,&v); if(!isconnect(u,v)){ puts("-1"); }else{ makeroot(u); access(v); splay(v); printf("%d\n",maxv[v]); } } } puts(""); } return 0; }
T7 bzoj3282
#include<cstdio> #include<algorithm> using namespace std; const int N=300005; int n,m,op,u,v,fa ,ch [2],rev ,val ,sumv ; bool isroot(int u){ return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u; } int which(int u){ return u==ch[fa[u]][1]; } void pushup(int u){ sumv[u]=val[u]; if(ch[u][0]){ sumv[u]^=sumv[ch[u][0]]; } if(ch[u][1]){ sumv[u]^=sumv[ch[u][1]]; } } void reverse(int u){ rev[u]^=1; swap(ch[u][0],ch[u][1]); } void downtag(int u){ if(rev[u]){ if(ch[u][0]){ reverse(ch[u][0]); } if(ch[u][1]){ reverse(ch[u][1]); } rev[u]=0; } } void pushdown(int u){ if(!isroot(u)){ pushdown(fa[u]); } downtag(u); } void rotate(int x){ int y=fa[x],z=fa[y],md=which(x); if(!isroot(y)){ ch[z][which(y)]=x; } fa[x]=z; ch[y][md]=ch[x][!md]; fa[ch[y][md]]=y; ch[x][!md]=y; fa[y]=x; pushup(y); pushup(x); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u])){ rotate(which(fa[u])==which(u)?fa[u]:u); } rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); ch[u][1]=v; pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } void link(int u,int v){ makeroot(u); fa[u]=v; } void cut(int u,int v){ makeroot(u); access(v); splay(v); fa[u]=ch[v][0]=0; pushup(v); } bool isconnect(int u,int v){ if(u==v){ return true; } makeroot(u); access(v); splay(v); return fa[u]!=0; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&val[i]); sumv[i]=val[i]; } for(int i=1;i<=m;i++){ scanf("%d%d%d",&op,&u,&v); if(op==0){ makeroot(u); access(v); splay(v); printf("%d\n",sumv[v]); }else if(op==1){ if(!isconnect(u,v)){ link(u,v); } }else if(op==2){ if(isconnect(u,v)&&u!=v){ cut(u,v); } }else{ makeroot(u); val[u]=v; pushup(u); } } return 0; }
T8 bzoj3669
#include<cstdio> #include<algorithm> using namespace std; const int N=150005,M=150005; int n,m,ans=0x7f7f7f7f,fa ,ch [2],rev ; struct edge{ int u,v,a,b,id; bool operator < (const edge &a) const{ return b<a.b; } }e[M],val ,maxv ; bool cmp(edge a,edge b){ return a.a<b.a; } bool isroot(int u){ return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u; } int which(int u){ return u==ch[fa[u]][1]; } void pushup(int u){ maxv[u]=val[u]; if(ch[u][0]){ maxv[u]=max(maxv[u],maxv[ch[u][0]]); } if(ch[u][1]){ maxv[u]=max(maxv[u],maxv[ch[u][1]]); } } void reverse(int u){ rev[u]^=1; swap(ch[u][0],ch[u][1]); } void downtag(int u){ if(rev[u]){ if(ch[u][0]){ reverse(ch[u][0]); } if(ch[u][1]){ reverse(ch[u][1]); } rev[u]=0; } } void pushdown(int u){ if(!isroot(u)){ pushdown(fa[u]); } downtag(u); } void rotate(int x){ int y=fa[x],z=fa[y],md=which(x); if(!isroot(y)){ ch[z][which(y)]=x; } fa[x]=z; ch[y][md]=ch[x][!md]; fa[ch[y][md]]=y; ch[x][!md]=y; fa[y]=x; pushup(y); pushup(x); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u])){ rotate(which(fa[u])==which(u)?fa[u]:u); } rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); ch[u][1]=v; pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } void link(int u,int v){ makeroot(u); fa[u]=v; } void cut(int u,int v){ makeroot(u); access(v); splay(v); fa[u]=ch[v][0]=0; pushup(v); } bool isconnect(int u,int v){ if(u==v){ return true; } makeroot(u); access(v); splay(v); return fa[u]!=0; } int main(){ scanf("%d%d",&n,&m); if(n==1){ puts("0"); return 0; } for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].a,&e[i].b); } sort(e+1,e+m+1,cmp); for(int i=1;i<=m;i++){ e[i].id=i; val[i+n]=maxv[i+n]=e[i]; } for(int i=1;i<=m;i++){ if(!isconnect(e[i].u,e[i].v)){ link(e[i].u,i+n); link(i+n,e[i].v); }else if(e[i].u!=e[i].v){ makeroot(e[i].u); access(e[i].v); splay(e[i].v); edge tmp=maxv[e[i].v]; if(e[i].b<maxv[e[i].v].b){ cut(tmp.u,tmp.id+n); cut(tmp.id+n,tmp.v); link(e[i].u,i+n); link(i+n,e[i].v); } } if(isconnect(1,n)){ makeroot(1); access(n); splay(n); ans=min(ans,e[i].a+maxv .b); } } printf("%d\n",ans==0x7f7f7f7f?-1:ans); return 0; }
T8 bzoj3306
和遥远的国度一题很像,只不过写了Link-Cut Tree。打了一个Treap。
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; const int N=100005; int n,q,rt,f,x,y,a ,fa ,rev ,minv ,ch [2]; int siz[N*50],w[N*50],val[N*50],rnd[N*50],c[N*50][2],mmp[N*50]; char s[10]; struct Treap{ int root; int qmin(){ int k=root; while(c[k][0]){ k=c[k][0]; } return val[k]; } void pushup(int u){ siz[u]=w[u]+siz[c[u][0]]+siz[c[u][1]]; } void rotate(int &y,int md){ int x=c[y][md]; c[y][md]=c[x][!md]; c[x][!md]=y; pushup(y); pushup(x); y=x; } void insert(int &k,int x){ if(!k){ k=mmp[mmp[0]--]; siz[k]=w[k]=1; c[k][0]=c[k][1]=0; val[k]=x; rnd[k]=rand(); return; } siz[k]++; if(x==val[k]){ w[k]++; }else{ int md=x>val[k]; insert(c[k][md],x); if(rnd[c[k][md]]<rnd[k]){ rotate(k,md); } } } void remove(int &k,int x){ siz[k]--; if(x==val[k]){ if(w[k]>1){ w[k]--; }else{ if(c[k][0]*c[k][1]==0){ mmp[++mmp[0]]=k; k=c[k][0]+c[k][1]; }else{ rotate(k,rnd[c[k][0]]>rnd[c[k][1]]); remove(k,x); } } }else{ remove(c[k][x>val[k]],x); } } }set ; bool isroot(int u){ return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u; } int which(int u){ return u==ch[fa[u]][1]; } int pushup(int u){ minv[u]=set[u].qmin(); if(ch[u][0]){ minv[u]=min(minv[u],minv[ch[u][0]]); } if(ch[u][1]){ minv[u]=min(minv[u],minv[ch[u][1]]); } } void reverse(int u){ rev[u]^=1; swap(ch[u][0],ch[u][1]); } void downtag(int u){ if(rev[u]){ if(ch[u][0]){ reverse(ch[u][0]); } if(ch[u][1]){ reverse(ch[u][1]); } rev[u]=0; } } void pushdown(int u){ if(!isroot(u)){ pushdown(fa[u]); } downtag(u); } void rotate(int x){ int y=fa[x],z=fa[y],md=which(x); if(!isroot(y)){ ch[fa[y]][which(y)]=x; } fa[x]=z; ch[y][md]=ch[x][!md]; fa[ch[y][md]]=y; ch[x][!md]=y; fa[y]=x; pushup(y); pushup(x); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u])){ rotate(which(fa[u])==which(u)?fa[u]:u); } rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); if(ch[u][1]){ set[u].insert(set[u].root,minv[ch[u][1]]); } ch[u][1]=v; if(ch[u][1]){ set[u].remove(set[u].root,minv[ch[u][1]]); } pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } int cnt,head ,to ,nxt ; void adde(int u,int v){ to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void dfs(int u){ int v; minv[u]=a[u]; set[u].insert(set[u].root,a[u]); for(int i=head[u];i;i=nxt[i]){ v=to[i]; dfs(v); fa[v]=u; set[u].insert(set[u].root,minv[v]); } pushup(u); } int main(){ for(int i=5000000;i>=1;i--){ mmp[++mmp[0]]=i; } scanf("%d%d",&n,&q); for(int i=1;i<=n;i++){ scanf("%d%d",&f,&a[i]); if(f){ adde(f,i); }else{ rt=i; } } dfs(rt); for(int i=1;i<=q;i++){ scanf("%s%d",s,&x); if(s[0]=='V'){ scanf("%d",&y); access(x); splay(x); set[x].remove(set[x].root,a[x]); a[x]=y; set[x].insert(set[x].root,a[x]); pushup(x); }else if(s[0]=='E'){ makeroot(x); }else{ access(x); splay(x); printf("%d\n",set[x].qmin()); } } return 0; }
T9 bzoj2959
#include<cstdio> #include<algorithm> using namespace std; const int N=150005; int n,m,op,u,v,fu0,fv0,fu1,fv1,pa [2],fa ,ch [2],rev ,val ,sumv ; int a ; int find(int u,int md){ return u==pa[u][md]?u:pa[u][md]=find(pa[u][md],md); } bool isroot(int u){ if(!fa[u]){ return true; } int tmp=find(fa[u],1); return u!=ch[tmp][0]&&u!=ch[tmp][1]; } int which(int u){ return u==ch[find(fa[u],1)][1]; } void pushup(int u){ if(!u){ return; } sumv[u]=val[u]+sumv[ch[u][0]]+sumv[ch[u][1]]; } void reverse(int u){ rev[u]^=1; swap(ch[u][0],ch[u][1]); } void downtag(int u){ if(rev[u]){ if(ch[u][0]){ reverse(ch[u][0]); } if(ch[u][1]){ reverse(ch[u][1]); } rev[u]=0; } } void pushdown(int u){ if(!isroot(u)){ pushdown(fa[u]); } downtag(u); } void rotate(int x){ int y=find(fa[x],1),z=find(fa[y],1),md=x==ch[y][1]; if(y==ch[z][0]||y==ch[z][1]){ ch[z][y==ch[z][1]]=x; } fa[x]=z; ch[y][md]=ch[x][!md]; if(ch[y][md]){ fa[ch[y][md]]=y; } ch[x][!md]=y; if(y){ fa[y]=x; } pushup(y); pushup(x); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u])){ rotate(which(fa[u])==which(u)?fa[u]:u); } rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=find(fa[u],1)){ splay(u); ch[u][1]=v; pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } int dfs(int rt,int u){ if(!u){ return 0; } pa[u][1]=rt; return dfs(rt,ch[u][0])+dfs(rt,ch[u][1])+val[u]; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ pa[i][0]=pa[i][1]=i; } for(int i=1;i<=n;i++){ scanf("%d",&a[i]); sumv[i]=val[i]=a[i]; } for(int i=1;i<=m;i++){ if(i==24){ u++; } scanf("%d%d%d",&op,&u,&v); if(op==1){ if((fu1=find(u,1))!=(fv1=find(v,1))){ if((fu0=find(u,0))!=(fv0=find(v,0))){ makeroot(fu1); fa[fu1]=fv1; pa[fv0][0]=fu0; }else{ makeroot(fu1); access(fv1); splay(fv1); val[fu1]=dfs(fu1,fv1); fa[fu1]=0; ch[fu1][0]=ch[fu1][1]=0; pushup(fu1); } } }else if(op==2){ splay(fu1=find(u,1)); val[fu1]-=a[u]; a[u]=v; val[fu1]+=a[u]; pushup(fu1); }else{ if(find(u,0)!=find(v,0)){ puts("-1"); continue; } fu1=find(u,1),fv1=find(v,1); makeroot(fu1); access(fv1); splay(fv1); printf("%d\n",sumv[fv1]); } } return 0; }
T10 bzoj2594
#include<cstdio> #include<algorithm> #include<set> using namespace std; inline int rd(){ char ch=getchar(); int ret=0,f=1; while(ch<'0'||ch>'9'){ if(ch=='-'){ f=-1; } ch=getchar(); } while(ch>='0'&&ch<='9'){ ret=ret*10+ch-'0'; ch=getchar(); } return ret*f; } const int N=100005,M=1000005; int n,m,tot,cnt,q,u,v,L ,R ,pa ; int head[N+M],to[4*N],nxt[4*N]; int fa[N+M],ch[N+M][2],rev[N+M],val[N+M],maxn[N+M],stk[N+M]; int find(int u){ return u==pa[u]?u:pa[u]=find(pa[u]); } struct edge{ int u,v,d,id; bool flag; }e1[M],e2[M]; struct operation{ int op,u,v,ans; }op ; bool cmp1(edge a,edge b){ return a.u==b.u?a.v<b.v:a.u<b.u; } bool cmp2(edge a,edge b){ return a.d<b.d; } void adde(int u,int v){ to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void dfs(int u){ int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=fa[u]){ fa[v]=u; dfs(v); } } } int find(int u,int v){ int l=L[u],r=R[u],mid; while(l<=r){ mid=(l+r)/2; if(e1[mid].v<v){ l=mid+1; }else if(e1[mid].v>v){ r=mid-1; }else{ return mid; } } } bool isroot(int u){ return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u; } int which(int u){ return u==ch[fa[u]][1]; } void pushup(int u){ if(u>n){ maxn[u]=u-n; }else{ maxn[u]=0; } if(e1[maxn[ch[u][0]]].d>e1[maxn[u]].d){ maxn[u]=maxn[ch[u][0]]; } if(e1[maxn[ch[u][1]]].d>e1[maxn[u]].d){ maxn[u]=maxn[ch[u][1]]; } } void reverse(int u){ rev[u]^=1; swap(ch[u][0],ch[u][1]); } void downtag(int u){ if(rev[u]){ if(ch[u][0]){ reverse(ch[u][0]); } if(ch[u][1]){ reverse(ch[u][1]); } rev[u]=0; } } void pushdown(int u){ stk[stk[0]=1]=u; for(;!isroot(u);u=fa[u]){ stk[++stk[0]]=fa[u]; } while(stk[0]){ downtag(stk[stk[0]--]); } } void rotate(int x){ int y=fa[x],z=fa[y],md=which(x); if(!isroot(y)){ ch[z][which(y)]=x; } fa[x]=z; ch[y][md]=ch[x][!md]; fa[ch[y][md]]=y; ch[x][!md]=y; fa[y]=x; pushup(y); pushup(x); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u])){ rotate(which(fa[u])==which(u)?fa[u]:u); } rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); ch[u][1]=v; pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } void link(int u,int v){ makeroot(u); fa[u]=v; } void cut(int u,int v){ makeroot(u); access(v); splay(v); fa[u]=ch[v][0]=0; pushup(v); } int main(){ n=rd(),m=rd(),q=rd(); for(int i=1;i<=m;i++){ e1[i].u=rd(),e1[i].v=rd(),e1[i].d=rd(); if(e1[i].u>e1[i].v){ e1[i].u^=e1[i].v; e1[i].v^=e1[i].u; e1[i].u^=e1[i].v; } } sort(e1+1,e1+m+1,cmp1); for(int i=1;i<=m;i++){ e1[i].id=i; maxn[i+n]=i; } L[1]=1; R =m; for(int i=2;i<=m;i++){ if(e1[i].u!=e1[i-1].u){ L[e1[i].u]=i; R[e1[i-1].u]=i-1; } } for(int i=1;i<=q;i++){ op[i].op=rd(),op[i].u=rd(),op[i].v=rd(); if(op[i].op==2){ if(op[i].u>op[i].v){ op[i].u^=op[i].v; op[i].v^=op[i].u; op[i].u^=op[i].v; } u=find(op[i].u,op[i].v); e1[u].flag=true; } } for(int i=1;i<=m;i++){ if(!e1[i].flag){ e2[++tot]=e1[i]; } } sort(e2+1,e2+tot+1,cmp2); for(int i=1;i<=n;i++){ pa[i]=i; } for(int i=1,j=0;i<=tot&&j!=n-1;i++){ u=find(e2[i].u),v=find(e2[i].v); if(u!=v){ j++; pa[v]=u; adde(e2[i].u,e2[i].id+n); adde(e2[i].id+n,e2[i].u); adde(e2[i].v,e2[i].id+n); adde(e2[i].id+n,e2[i].v); } } dfs(1); for(int i=q;i>=1;i--){ if(op[i].op==1){ makeroot(op[i].u); access(op[i].v); splay(op[i].v); op[i].ans=e1[maxn[op[i].v]].d; }else{ makeroot(op[i].u); access(op[i].v); splay(op[i].v); u=maxn[op[i].v],v=find(op[i].u,op[i].v); if(e1[u].d>e1[v].d){ cut(e1[u].u,u+n); cut(u+n,e1[u].v); link(e1[v].u,v+n); link(v+n,e1[v].v); } } } for(int i=1;i<=q;i++){ if(op[i].op==1){ printf("%d\n",op[i].ans); } } return 0; }
T11 uva11994
各种乱搞之后终于过了!仍然把边变成点。
其实我的代码判断祖孙关系非常暴力,可以被卡。暂时没想到怎么在动态树中快速判断祖孙关系==
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=50005; int n,m,op,u,v,c,cnt,ans,pa ,rt ; int fa[N*2],ch[N*2][2],rev[N*2],tag[N*2],sumv[N*2],siz[N*2],val[N*2],stk[N*2]; int head[N*2],to[N*4],nxt[N*4]; void adde(int u,int v){ to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void dfs(int u){ int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=fa[u]){ fa[v]=u; dfs(v); } } } bool isroot(int u){ return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u; } int which(int u){ return u==ch[fa[u]][1]; } void pushup(int u){ sumv[u]=1<<val[u]; siz[u]=1; if(ch[u][0]){ sumv[u]|=sumv[ch[u][0]]; siz[u]+=siz[ch[u][0]]; } if(ch[u][1]){ sumv[u]|=sumv[ch[u][1]]; siz[u]+=siz[ch[u][1]]; } } void reverse(int u){ rev[u]^=1; swap(ch[u][0],ch[u][1]); } void maintain(int u,int c){ tag[u]=c; sumv[u]=1<<c; if(u>n){ val[u]=c; } } void downtag(int u){ if(rev[u]){ if(ch[u][0]){ reverse(ch[u][0]); } if(ch[u][1]){ reverse(ch[u][1]); } rev[u]=0; } if(tag[u]){ if(ch[u][0]){ maintain(ch[u][0],tag[u]); } if(ch[u][1]){ maintain(ch[u][1],tag[u]); } tag[u]=0; } } void pushdown(int u){ stk[stk[0]=1]=u; for(;!isroot(u);u=fa[u]){ stk[++stk[0]]=fa[u]; } while(stk[0]){ downtag(stk[stk[0]--]); } } void rotate(int x){ int y=fa[x],z=fa[y],md=which(x); if(!isroot(y)){ ch[z][which(y)]=x; } fa[x]=z; ch[y][md]=ch[x][!md]; fa[ch[y][md]]=y; ch[x][!md]=y; fa[y]=x; pushup(y); pushup(x); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u])){ rotate(which(fa[u])==which(u)?fa[u]:u); } rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); ch[u][1]=v; pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } void link(int u,int v){ makeroot(u); fa[u]=v; } void cut(int u,int v){ makeroot(u); access(v); splay(v); fa[u]=ch[v][0]=0; pushup(v); } bool judge(int u,int v){ while(v){ if(u==v){ return false; } v=pa[v]; } return true; } bool isconnect(int u,int v){ if(u==v){ return true; } makeroot(u); access(v); splay(v); return fa[u]!=0; } int main(){ while(~scanf("%d%d",&n,&m)){ memset(fa,0,sizeof(fa)); memset(ch,0,sizeof(ch)); memset(rev,0,sizeof(rev)); memset(tag,0,sizeof(tag)); memset(sumv,0,sizeof(sumv)); memset(siz,0,sizeof(siz)); memset(val,0,sizeof(val)); memset(head,0,sizeof(head)); rt[0]=cnt=0; for(int i=1;i<=n;i++){ scanf("%d",&pa[i]); if(pa[i]){ adde(pa[i],i+n); adde(i+n,pa[i]); adde(i,i+n); adde(i+n,i); }else{ rt[++rt[0]]=i; } } for(int i=1;i<=n;i++){ scanf("%d",&val[i+n]); sumv[i+n]=1<<val[i+n]; siz[i]=siz[i+n]=1; } for(int i=1;i<=rt[0];i++){ dfs(rt[i]); } for(int i=1;i<=m;i++){ scanf("%d%d%d",&op,&u,&v); if(op==1){ scanf("%d",&c); if(judge(u,v)){ if(pa[u]){ cut(pa[u],u+n); cut(u+n,u); } pa[u]=v; link(pa[u],u+n); link(u+n,u); splay(u+n); val[u+n]=c; pushup(u+n); } }else if(op==2){ scanf("%d",&c); if(u!=v&&isconnect(u,v)){ makeroot(u); access(v); splay(v); maintain(v,c); } }else{ if(u==v||!isconnect(u,v)){ puts("0 0"); }else{ makeroot(u); access(v); splay(v); ans=0; for(int j=1;j<=30;j++){ if(sumv[v]&(1<<j)){ ans++; } } printf("%d %d\n",(siz[v]-1)/2,ans); } } } } return 0; }
相关文章推荐
- BZOJ 题目2002: [Hnoi2010]Bounce 弹飞绵羊(link cut tree)
- BZOJ 题目1036: [ZJOI2008]树的统计Count(Link Cut Tree,修改点权求两个最大值和最大值)
- 【Learning】一步步地解释Link-cut Tree
- BZOJ 题目2049: [Sdoi2008]Cave 洞穴勘测(link cut tree)
- HDOJ 题目4010 Query on The Trees(Link Cut Tree连接,删边,路径点权加,路径点权最大值)
- 【Learning】倍增求LCA题目汇总
- 【Learning】动态树分治题目汇总
- 【Learning】虚树题目汇总
- 【learning】树形dp题目汇总
- BZOJ 题目1036: [ZJOI2008]树的统计Count(Link Cut Tree,改动点权求两个最大值和最大值)
- 面试10大算法汇总+常见题目解答
- 栈和队列相关题目汇总
- 【UOJ207】共价大爷游长沙(Link-Cut Tree,随机化)
- 剑指offer编程题目汇总(更新中。。)
- C/C++ 笔试、面试题目大汇总
- 面试题目汇总(JAVA算法/数据结构)
- 面试之C++题目汇总7
- C/C++ 笔试、面试题目大汇总
- 计算机网络---基础题目汇总七
- C/C++ 笔试、面试题目大汇总