BZOJ3091: 城市旅行(LCT,数学期望)

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

解题思路:

大爷比我讲得好到不知道哪里去了PoPoQQQ的博客

 

就是考虑一个点会被经过多少次*多少贡献,感觉这个好套路,线性求解不是问题,不会动态维护QAQ。

考虑一个点代表的子树信息内部处理完毕,处理左子树对右子树或右子树对左子树的影响,像分治的想法QAQ。

最后累计答案就累计左子树答案+右子树答案+自己答案+左对右答案+右对左答案就好了。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll tr[spc].ch[0]
  5 #define rrr tr[spc].ch[1]
  6 #define ls ch[0]
  7 #define rs ch[1]
  8 typedef long long lnt;
  9 const int N=100010;
 10 struct trnt{
 11     int ch[2];
 12     int fa;
 13     int lzt;
 14     int wgt;
 15     lnt add;
 16     lnt val;
 17     lnt ans;
 18     lnt sum;
 19     lnt lsum;
 20     lnt rsum;
 21     bool anc;
 22 }tr[N];
 23 int n,m;
 24 bool whc(int spc)
 25 {
 26     return tr[tr[spc].fa].rs==spc;
 27 }
 28 void pushup(int spc)
 29 {
 30     if(!spc)
 31         return ;
 32     tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+1;
 33     tr[spc].sum=tr[lll].sum+tr[rrr].sum+tr[spc].val;
 34     tr[spc].lsum=tr[lll].lsum+tr[rrr].lsum+tr[spc].val*(tr[lll].wgt+1)+tr[rrr].sum*(tr[lll].wgt+1);
 35     tr[spc].rsum=tr[lll].rsum+tr[rrr].rsum+tr[spc].val*(tr[rrr].wgt+1)+tr[lll].sum*(tr[rrr].wgt+1);
 36     tr[spc].ans=tr[lll].ans+tr[rrr].ans+tr[lll].lsum*(tr[rrr].wgt+1)+tr[rrr].rsum*(tr[lll].wgt+1)+tr[spc].val*(tr[lll].wgt+1)*(tr[rrr].wgt+1);
 37     return ;
 38 }
 39 void Add(int spc,lnt v)
 40 {
 41     if(!spc)
 42         return ;
 43     tr[spc].add+=v;
 44     tr[spc].val+=v;
 45     tr[spc].sum+=v*tr[spc].wgt;
 46     tr[spc].lsum+=v*(tr[spc].wgt)*(tr[spc].wgt+1)/2;
 47     tr[spc].rsum+=v*(tr[spc].wgt)*(tr[spc].wgt+1)/2;
 48     tr[spc].ans+=v*(tr[spc].wgt+2)*(tr[spc].wgt+1)*tr[spc].wgt/6;
 49     return ;
 50 }
 51 void trr(int spc)
 52 {
 53     if(!spc)
 54         return ;
 55     tr[spc].lzt^=1;
 56     std::swap(lll,rrr);
 57     std::swap(tr[spc].lsum,tr[spc].rsum);
 58     return ;
 59 }
 60 void pushdown(int spc)
 61 {
 62     if(tr[spc].lzt)
 63     {
 64         trr(lll);
 65         trr(rrr);
 66         tr[spc].lzt=0;
 67     }
 68     if(tr[spc].add)
 69     {
 70         Add(lll,tr[spc].add);
 71         Add(rrr,tr[spc].add);
 72         tr[spc].add=0;
 73     }
 74     return ;
 75 }
 76 void recal(int spc)
 77 {
 78     if(!tr[spc].anc)
 79         recal(tr[spc].fa);
 80     pushdown(spc);
 81     return ;
 82 }
 83 void rotate(int spc)
 84 {
 85     int f=tr[spc].fa;
 86     bool k=whc(spc);
 87     tr[f].ch[k]=tr[spc].ch[!k];
 88     tr[spc].ch[!k]=f;
 89     if(tr[f].anc)
 90     {
 91         tr[spc].anc=true;
 92         tr[f].anc=false;
 93     }else
 94         tr[tr[f].fa].ch[whc(f)]=spc;
 95     tr[spc].fa=tr[f].fa;
 96     tr[f].fa=spc;
 97     tr[tr[f].ch[k]].fa=f;
 98     pushup(f);
 99     pushup(spc);
100     return ;
101 }
102 void splay(int spc)
103 {
104     recal(spc);
105     while(!tr[spc].anc)
106     {
107         int f=tr[spc].fa;
108         if(tr[f].anc)
109         {
110             rotate(spc);
111             return ;
112         }
113         if(whc(spc)^whc(f))
114             rotate(spc);
115         else
116             rotate(f);
117         rotate(spc);
118     }
119     return ;
120 }
121 void access(int spc)
122 {    
123     int lst=0;
124     while(spc)
125     {
126         splay(spc);
127         tr[rrr].anc=true;
128         tr[lst].anc=false;
129         rrr=lst;
130         pushup(spc);
131         lst=spc;
132         spc=tr[spc].fa;
133     }
134     return ;
135 }
136 void Mtr(int spc)
137 {
138     access(spc);
139     splay(spc);
140     trr(spc);
141     return ;
142 }
143 void split(int x,int y)
144 {
145     Mtr(x);
146     access(y);
147     splay(y);
148     return ;
149 }
150 bool together(int x,int y)
151 {
152     split(x,y);
153     while(tr[y].ls)
154         y=tr[y].ls;
155     return x==y;
156 }
157 void link(int x,int y)
158 {
159     split(x,y);
160     tr[x].fa=y;
161     return ;
162 }
163 void cut(int x,int y)
164 {
165     split(x,y);
166     tr[y].ls=0;
167     tr[x].fa=0;
168     tr[x].anc=true;
169     pushup(y);
170     return ;
171 }
172 lnt gcd(lnt a,lnt b)
173 {
174     if(!b)
175         return a;
176     return gcd(b,a%b);
177 }
178 int main()
179 {
180     scanf("%d%d",&n,&m);
181     for(int i=1;i<=n;i++)
182     {
183         scanf("%lld",&tr[i].val);
184         tr[i].anc=true;
185         pushup(i);
186     }
187     for(int i=1;i<n;i++)
188     {
189         int a,b;
190         scanf("%d%d",&a,&b);
191         link(a,b);
192     }
193     while(m--)
194     {
195         int cmd;
196         scanf("%d",&cmd);
197         if(cmd==1)
198         {
199             int u,v;
200             scanf("%d%d",&u,&v);
201             if(together(u,v))
202                 cut(u,v);
203         }else if(cmd==2)
204         {
205             int u,v;
206             scanf("%d%d",&u,&v);
207             if(!together(u,v))
208                 link(u,v);
209         }else if(cmd==3)
210         {
211             int u,v,d;
212             scanf("%d%d%d",&u,&v,&d);
213             if(together(u,v))
214                 Add(v,d);
215         }else{
216             int u,v;
217             scanf("%d%d",&u,&v);
218             if(!together(u,v))
219                 printf("%d\n",-1);
220             else{
221                 lnt top=tr[v].ans;
222                 lnt bot=(lnt)(tr[v].wgt)*(lnt)(tr[v].wgt+1)/2;
223                 lnt c=gcd(top,bot);
224                 top/=c,bot/=c;
225                 printf("%lld/%lld\n",top,bot);
226             }
227         }
228     }
229     return 0;
230 }

 

posted @ 2018-12-21 20:54  Unstoppable728  阅读(293)  评论(0编辑  收藏  举报