题目链接:hdu 5002 Tree
题意:
给你一棵树,每个节点有个权值。
现在有四种操作
1. 删一条边加一条边,保证操作后还是一棵树。
2. 将一条链的节点的权值设为x.
3. 将一条链的节点的权值加上x.
4. 询问一条链的第二大权值,并且输出有多少个。
题解:
很裸的LCT,维护一下就行了。
1 #include2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 #define mst(a,b) memset(a,b,sizeof(a)) 4 using namespace std; 5 typedef pair<int,int>P; 6 7 namespace LCT 8 { 9 const int N=1e5+7,inf=2e9+7; 10 int f[N],son[N][2],val[N],tmp[N],sum[N],lazy[N],laop[N]; 11 int g[N],v[N*2],nxt[N*2],ed;bool rev[N]; 12 P mx[N][2],tp[10]; 13 void clear(int n) 14 { 15 F(i,1,n)f[i]=son[i][0]=son[i][1]=0; 16 F(i,1,n)rev[i]=lazy[i]=laop[i]=g[i]=0;ed=0; 17 F(i,1,n)mx[i][0]=mx[i][1]=P(-inf,0); 18 } 19 void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;} 20 void build(int x=1){ 21 sum[x]=1,mx[x][0]=P(val[x],1); 22 for(int i=g[x];i;i=nxt[i]) 23 if(!f[v[i]]&&v[i]!=1)f[v[i]]=x,build(v[i]); 24 } 25 bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;} 26 void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]);rev[x]^=1;} 27 void add(int x,int c,int op) 28 { 29 if(!x)return; 30 if(op==2) 31 { 32 val[x]+=c,lazy[x]+=c; 33 mx[x][0].first+=c; 34 if(mx[x][1].first!=-inf)mx[x][1].first+=c; 35 } 36 else if(op==1) 37 { 38 val[x]=c,lazy[x]=c; 39 mx[x][0]=P(c,sum[x]); 40 mx[x][1]=P(-inf,0); 41 laop[x]=1; 42 } 43 if(!laop[x])laop[x]=op; 44 } 45 void pb(int x){ 46 if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0; 47 if(laop[x])add(son[x][0],lazy[x],laop[x]),add(son[x][1],lazy[x],laop[x]),lazy[x]=laop[x]=0; 48 } 49 void up(int x){ 50 sum[x]=1; 51 int ct=0; 52 tp[ct=1]=P(val[x],1); 53 if(son[x][0]) 54 { 55 sum[x]+=sum[son[x][0]]; 56 F(i,0,1)tp[++ct]=mx[son[x][0]][i]; 57 } 58 if(son[x][1]) 59 { 60 sum[x]+=sum[son[x][1]]; 61 F(i,0,1)tp[++ct]=(mx[son[x][1]][i]); 62 } 63 sort(tp+1,tp+1+ct,greater ()); 64 int cnt=1; 65 F(i,2,ct) 66 { 67 if(tp[i].first==tp[cnt].first)tp[cnt].second+=tp[i].second; 68 else tp[++cnt]=tp[i]; 69 } 70 mx[x][0]=tp[1]; 71 if(cnt>1)mx[x][1]=tp[2]; 72 else mx[x][1]=P(-inf,0); 73 } 74 void rotate(int x){ 75 int y=f[x],w=son[y][1]==x; 76 son[y][w]=son[x][w^1]; 77 if(son[x][w^1])f[son[x][w^1]]=y; 78 if(f[y]){ 79 int z=f[y]; 80 if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x; 81 } 82 f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y); 83 } 84 void splay(int x){ 85 int s=1,i=x,y;tmp[1]=i; 86 while(!isroot(i))tmp[++s]=i=f[i]; 87 while(s)pb(tmp[s--]); 88 while(!isroot(x)){ 89 y=f[x]; 90 if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);} 91 rotate(x); 92 } 93 up(x); 94 } 95 void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);} 96 int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;} 97 void makeroot(int x){access(x);splay(x);rev1(x);} 98 void link(int x,int y){makeroot(x);f[x]=y;access(x);} 99 void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;up(x);} 100 void cut(int x,int y){makeroot(x);cutf(y);} 101 void update(int x,int y,int c,int op){makeroot(x),access(y),splay(y),add(y,c,op);} 102 P ask(int x,int y){makeroot(x);access(y);splay(y);return mx[y][1];} 103 } 104 using namespace LCT; 105 int t,n,m,c,a,b,x,y,cas; 106 107 int main() 108 { 109 scanf("%d",&t); 110 while(t--) 111 { 112 scanf("%d%d",&n,&m); 113 clear(n); 114 F(i,1,n)scanf("%d",val+i); 115 F(i,2,n) 116 { 117 scanf("%d%d",&x,&y); 118 adg(x,y),adg(y,x); 119 } 120 build(),printf("Case #%d:\n",++cas); 121 F(i,1,m) 122 { 123 scanf("%d",&c); 124 if(c==1) 125 { 126 scanf("%d%d%d%d",&x,&y,&a,&b); 127 cut(x,y),link(a,b); 128 } 129 else if(c==2) 130 { 131 scanf("%d%d%d",&a,&b,&x); 132 update(a,b,x,1); 133 } 134 else if(c==3) 135 { 136 scanf("%d%d%d",&a,&b,&x); 137 update(a,b,x,2); 138 } 139 else 140 { 141 scanf("%d%d",&a,&b); 142 P ans=ask(a,b); 143 if(ans.first==-inf)puts("ALL SAME"); 144 else printf("%d %d\n",ans.first,ans.second); 145 } 146 147 } 148 } 149 return 0; 150 }