bzoj3091: 城市旅行
Posted weeping
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3091: 城市旅行相关的知识,希望对你有一定的参考价值。
地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3091
题目:
3091: 城市旅行
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1839 Solved: 599
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
4 5
1 3 2 5
1 2
1 3
2 4
4 2 4
1 2 4
2 3 4
3 1 4 1
4 1 4
1 3 2 5
1 2
1 3
2 4
4 2 4
1 2 4
2 3 4
3 1 4 1
4 1 4
Sample Output
16/3
6/1
6/1
HINT
对于所有数据满足 1<=N<=50,000 1<=M<=50,000 1<=Ai<=10^6 1<=D<=100 1<=U,V<=N
吐槽:
强行把裸lct变难。
思路:
看popoqqq的博客吧。。。
注意reverse操作时要swap(lsum,rsum).
1 /************************************************************** 2 Problem: 3091 3 User: weeping 4 Language: C++ 5 Result: Accepted 6 Time:3332 ms 7 Memory:5796 kb 8 ****************************************************************/ 9 10 #include <bits/stdc++.h> 11 12 typedef long long LL; 13 14 using namespace std; 15 16 struct Link_Cut_Tree 17 { 18 static const int MAXN = 60000 + 7; 19 20 int ch[MAXN][2], fa[MAXN], rev[MAXN]; 21 LL v[MAXN], lz[MAXN], sz[MAXN], sum[MAXN], lsum[MAXN], rsum[MAXN], ep[MAXN]; 22 int sk[MAXN]; 23 24 bool isroot(int x) 25 { 26 return ch[fa[x]][0] != x && ch[fa[x]][1] != x; 27 } 28 29 void reverse(int x) 30 { 31 rev[x] ^= 1, swap(ch[x][0],ch[x][1]), swap(lsum[x],rsum[x]); 32 } 33 void lazy(int x,LL d) 34 { 35 v[x] += d, lz[x] += d, sum[x] += sz[x] * d; 36 lsum[x] += sz[x] * (sz[x] + 1) / 2 * d; 37 rsum[x] += sz[x] * (sz[x] + 1) / 2 * d; 38 ep[x] += sz[x] * (sz[x] + 1) * (sz[x] + 2) / 6 * d; 39 } 40 void update(int x) 41 { 42 int lc = ch[x][0], rc = ch[x][1]; 43 sz[x] = sz[lc] + sz[rc] + 1; 44 sum[x] = sum[lc] + sum[rc] + v[x]; 45 lsum[x] = lsum[lc] + lsum[rc] + (sz[lc] + 1) * (sum[rc] + v[x]); 46 rsum[x] = rsum[lc] + rsum[rc] + (sz[rc] + 1) * (sum[lc] + v[x]); 47 ep[x] = ep[lc] + ep[rc] + lsum[lc]*(sz[rc]+1) + rsum[rc]*(sz[lc]+1) + v[x]*(sz[lc]+1)*(sz[rc]+1); 48 } 49 50 void push_down(int x) 51 { 52 if(rev[x]) 53 { 54 if(ch[x][0]) reverse(ch[x][0]); 55 if(ch[x][1]) reverse(ch[x][1]); 56 rev[x]=0; 57 } 58 if(lz[x]) 59 { 60 if(ch[x][0]) lazy(ch[x][0],lz[x]); 61 if(ch[x][1]) lazy(ch[x][1],lz[x]); 62 lz[x]=0; 63 } 64 } 65 66 void rotate(int x) 67 { 68 int f = fa[x], gf = fa[f]; 69 int t1 = ( x != ch[f][0]), t2 = ( f != ch[gf][0]), tmp = ch[x][1^t1]; 70 if(!isroot(f)) ch[gf][0^t2] = x; 71 fa[tmp] = f, fa[x] = gf, ch[x][1^t1] = f, fa[f] = x, ch[f][0^t1] = tmp; 72 update(f); 73 } 74 75 void splay(int x) 76 { 77 int top = 0; 78 sk[++top] = x; 79 for(int i = x; !isroot(i); i = fa[i]) sk[++top] = fa[i]; 80 while(top) push_down(sk[top--]); 81 for(int f = fa[x], gf = fa[f]; !isroot(x); rotate(x), f = fa[x],gf = fa[f]) 82 if(!isroot(f)) 83 rotate((x==ch[f][0]) ^ (f==ch[gf][0]) ? x : f); 84 update(x); 85 } 86 87 void access(int x) 88 { 89 for(int p = 0; x; p = x, x = fa[x]) 90 splay(x), ch[x][1] = p, update(x); 91 } 92 93 void makeroot(int x) 94 { 95 access(x), splay(x), reverse(x); 96 } 97 98 int findroot(int x) 99 { 100 access(x), splay(x); 101 while(ch[x][0]) x = ch[x][0]; 102 return x; 103 } 104 void link(int x,int y) 105 { 106 makeroot(x), fa[x] = y; 107 } 108 109 void cut(int x,int y) 110 { 111 makeroot(x), access(y), splay(y); 112 if(ch[y][0] == x) ch[y][0] = fa[x] = 0; 113 update(y); 114 } 115 116 void debug(void) 117 { 118 for(int i=1;i<=100;i++) 119 printf("%d %d %d %d %d %d %d\n",i,fa[i],ch[i][0],ch[i][1],rev[i],sz[i]); 120 } 121 122 void work(int n) 123 { 124 int op,x,y,z; 125 scanf("%d%d%d",&op,&x,&y); 126 if(op==1) 127 { 128 if(findroot(x)==findroot(y)) 129 cut(x,y); 130 } 131 else if(op==2) 132 { 133 if(findroot(x)!=findroot(y)) 134 link(x,y); 135 } 136 else if(op==3) 137 { 138 scanf("%d",&z); 139 if(findroot(x) == findroot(y)) 140 makeroot(x),access(y),splay(y),lazy(y,z); 141 } 142 else 143 { 144 if(findroot(x)!=findroot(y)) 145 { 146 printf("-1\n");return ; 147 } 148 makeroot(x),access(y),splay(y); 149 LL ta = ep[y],tb = sz[y] * (sz[y] + 1) / 2; 150 LL tc = __gcd(ta,tb); 151 printf("%lld/%lld\n",ta/tc,tb/tc); 152 } 153 } 154 }lct; 155 156 int n,m; 157 158 int main(void) 159 { 160 scanf("%d%d",&n,&m); 161 for(int i=1,x;i<=n;i++) 162 scanf("%d",&x),lct.sz[i]=1,lct.v[i]=x; 163 for(int i=1,x,y;i<n;i++) 164 scanf("%d%d",&x,&y),lct.link(x,y); 165 while(m--) lct.work(n); 166 return 0; 167 }
以上是关于bzoj3091: 城市旅行的主要内容,如果未能解决你的问题,请参考以下文章