BZOJ3091: 城市旅行(LCT,數學期望)
阿新 • • 發佈:2018-12-21
Description
Input
Output
Sample Input
4 51 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/36/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 intfa; 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 }