bzoj3091: 城市旅行

地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3091

题目:

3091: 城市旅行

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

16/3
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
",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
");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
",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 }
原文地址:https://www.cnblogs.com/weeping/p/7617219.html