题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4010
题意:一棵树,四种操作:
(1)若x和y不在一棵树上,将x和y连边;
(2)若x和y在一棵树上,将x变成树根,将y从x树上分离;
(3)若x和y在一棵树上,将x到y路径上的所有值增加det;
(4)若x和y在一棵树上,输出x到y路径上的最大值。
思路:1操作用link维护,2操作用cut,34操作先split(x,y),然后对y做tag,并且记录路径的max值。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<string> 6 #include<algorithm> 7 int tot,go[600005],next[600005],first[300005]; 8 int ch[600005][2],rev[600005],tag[600005],q[600005]; 9 int st[600005],mx[600005],fa[600005],v[600005]; 10 bool pd(int x){ 11 return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; 12 } 13 void insert(int x,int y){ 14 tot++;go[tot]=y;next[tot]=first[x];first[x]=tot; 15 } 16 void addedge(int x,int y){ 17 insert(x,y);insert(y,x); 18 } 19 void pushdown(int x){ 20 int l=ch[x][0],r=ch[x][1]; 21 if (rev[x]){ 22 rev[x]^=1;rev[l]^=1;rev[r]^=1; 23 std::swap(ch[x][0],ch[x][1]); 24 } 25 if (tag[x]){ 26 if (l) tag[l]+=tag[x],v[l]+=tag[x],mx[l]+=tag[x]; 27 if (r) tag[r]+=tag[x],mx[r]+=tag[x],v[r]+=tag[x]; 28 tag[x]=0; 29 } 30 } 31 void updata(int x){ 32 int l=ch[x][0],r=ch[x][1]; 33 mx[x]=std::max(v[x],std::max(mx[l],mx[r])); 34 } 35 void rotate(int x){ 36 int y=fa[x],z=fa[y],l,r; 37 if (ch[y][0]==x) l=0;else l=1;r=l^1; 38 if (!pd(y)){ 39 if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x; 40 } 41 fa[x]=z;fa[y]=x;fa[ch[x][r]]=y; 42 ch[y][l]=ch[x][r];ch[x][r]=y; 43 updata(y);updata(x); 44 } 45 void splay(int x){ 46 int top=0;st[++top]=x; 47 for (int i=x;!pd(i);i=fa[i]) 48 st[++top]=fa[i]; 49 for (int i=top;i;i--) 50 pushdown(st[i]); 51 while (!pd(x)){ 52 int y=fa[x],z=fa[y]; 53 if (!pd(y)){ 54 if (ch[y][0]==x^ch[z][0]==y) rotate(x); 55 else rotate(y); 56 } 57 rotate(x); 58 } 59 } 60 void access(int x){ 61 for (int t=0;x;t=x,x=fa[x]){ 62 splay(x); 63 ch[x][1]=t; 64 updata(x); 65 } 66 } 67 void makeroot(int x){ 68 access(x);splay(x);rev[x]^=1; 69 } 70 void cut(int x,int y){ 71 makeroot(x);access(y);splay(y);ch[y][0]=fa[ch[y][0]]=0;updata(y); 72 } 73 void link(int x,int y){ 74 makeroot(x); 75 fa[x]=y; 76 } 77 int find(int x){ 78 access(x);splay(x); 79 while (ch[x][0]) x=ch[x][0]; 80 return x; 81 } 82 void add(int x,int y,int val){ 83 makeroot(x);access(y);splay(y); 84 mx[y]+=val;v[y]+=val;tag[y]+=val; 85 } 86 int main(){ 87 int n,x,y,m,opt,w; 88 while (scanf("%d",&n)!=EOF){ 89 mx[0]=-2000000000; 90 for (int i=0;i<=n;i++) 91 mx[i]=tag[i]=rev[i]=v[i]=ch[i][0]=ch[i][1]=fa[i]=0; 92 memset(first,0,sizeof first);tot=0; 93 for (int i=1;i<n;i++){ 94 scanf("%d%d",&x,&y); 95 addedge(x,y); 96 } 97 for (int i=1;i<=n;i++){ 98 scanf("%d",&v[i]); 99 mx[i]=v[i]; 100 } 101 int top=1; 102 q[top]=1; 103 for (int k=1;k<=top;k++){ 104 for (int i=first[q[k]];i;i=next[i]){ 105 int pur=go[i]; 106 if (pur==fa[q[k]]) continue; 107 fa[pur]=q[k]; 108 q[++top]=pur; 109 } 110 } 111 top=0; 112 scanf("%d",&m); 113 while (m--){ 114 scanf("%d",&opt); 115 if (opt==1){ 116 scanf("%d%d",&x,&y); 117 if (find(x)==find(y)) {puts("-1");continue;} 118 link(x,y); 119 } 120 else 121 if (opt==2){ 122 scanf("%d%d",&x,&y); 123 if (find(x)!=find(y)||x==y) {puts("-1");continue;} 124 cut(x,y); 125 } 126 else 127 if (opt==3){ 128 scanf("%d%d%d",&w,&x,&y); 129 if (find(x)!=find(y)){puts("-1");continue;} 130 add(x,y,w); 131 } 132 else 133 if (opt==4) 134 { 135 scanf("%d%d",&x,&y); 136 if (find(x)!=find(y)){ 137 printf("-1 "); 138 continue; 139 } 140 makeroot(x);access(y);splay(y); 141 printf("%d ",mx[y]); 142 } 143 } 144 printf(" "); 145 } 146 }