Wannafly挑戰賽21 E 未來城市規劃
阿新 • • 發佈:2018-09-29
display line isp n) != amp can 端點 () \[size_x*\sum_{i(to_i在x子樹裏,to_i \neq x)} w_i*size_{to_i}-w_i*{size_{to_i}}^2\]
傳送門
題目中給的信息很難直接維護,但是可以考慮一條邊對答案的貢獻
在以\(x\)為根的子樹裏,如果一條邊\(i\)的權值為\(w_i\),這條邊深度更深的端點為\(to_i\),那麽這條邊對這個子樹的貢獻為\(w_i*size_x*(size_x-size_{to_i})\),也就是這條邊會被計算邊兩端點個數之積次
那麽一個子樹的答案就是\[\sum_{i(to_i在x子樹裏,to_i \neq x)} w_i*size_{to_i}*(size_x-size_{to_i})\]
即\[\sum_{i(to_i在x子樹裏,to_i \neq x)} w_i*size_x*size_{to_i}-w_i*{size_{to_i}}^2\]
然後把邊權\(w_i\)保存在\(to_i\)上,維護\(w_i*size_{to_i}\)和\(w_i*{size_{to_i}}^2\)就是個板子題了
#include<bits/stdc++.h> #define LL long long #define il inline #define re register #define db double #define eps (1e-7) using namespace std; const int N=70000+10,M=50000+10,mod=2019; il LL rd() { re LL x=0,w=1;re char ch=0; while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*w; } il int max(int a,int b){return a>b?a:b;} il int min(int a,int b){return a<b?a:b;} int s1[N<<2],s2[N<<2],z1[N<<2],z2[N<<2],s[N<<2],lz[N<<2]; #define lc (o<<1) #define rc ((o<<1)|1) #define mid ((l+r)>>1) il void psup(int o){s1[o]=(s1[lc]+s1[rc])%mod,s2[o]=(s2[lc]+s2[rc])%mod;} il void psdn(int o) { if(lz[o]) { s1[lc]=(s1[lc]+z1[lc]*lz[o]%mod)%mod,s2[lc]=(s2[lc]+z2[lc]*lz[o]%mod)%mod,lz[lc]=(lz[lc]+lz[o])%mod; s1[rc]=(s1[rc]+z1[rc]*lz[o]%mod)%mod,s2[rc]=(s2[rc]+z2[rc]*lz[o]%mod)%mod,lz[rc]=(lz[rc]+lz[o])%mod; lz[o]=0; } } void modif(int o,int l,int r,int ll,int rr,int x) { if(ll<=l&&r<=rr) { s1[o]=(s1[o]+z1[o]*x%mod)%mod,s2[o]=(s2[o]+z2[o]*x%mod)%mod,lz[o]=(lz[o]+x)%mod; psdn(o); return; } psdn(o); if(ll<=mid) modif(lc,l,mid,ll,rr,x); if(rr>mid) modif(rc,mid+1,r,ll,rr,x); psup(o); } int quer1(int o,int l,int r,int ll,int rr) { if(ll<=l&&r<=rr) return s1[o]; psdn(o); int an=0; if(ll<=mid) an+=quer1(lc,l,mid,ll,rr); if(rr>mid) an+=quer1(rc,mid+1,r,ll,rr); psup(o); return an%mod; } int quer2(int o,int l,int r,int ll,int rr) { if(ll<=l&&r<=rr) return s2[o]; //psdn(o); int an=0; if(ll<=mid) an+=quer2(lc,l,mid,ll,rr); if(rr>mid) an+=quer2(rc,mid+1,r,ll,rr); //psup(o); return an%mod; } int to[M<<1],nt[M<<1],w[M<<1],hd[N],tot=1; il void add(int x,int y,int z) { ++tot,to[tot]=y,nt[tot]=hd[x],w[tot]=z,hd[x]=tot; } int sz[M],son[M],de[M],fa[M],top[M],id[M],a[M],b[M],ti; void dfs1(int x) { sz[x]=1; for(int i=hd[x];i;i=nt[i]) { int y=to[i]; //if(y==fa[x]) continue; /*fa[y]=x,*/de[y]=de[x]+1; dfs1(y); sz[x]+=sz[y]; if(sz[y]>sz[son[x]]) son[x]=y; } } void dfs2(int x) { id[x]=++ti,b[ti]=x; if(son[x]) top[son[x]]=top[x],dfs2(son[x]); for(int i=hd[x];i;i=nt[i]) { int y=to[i]; if(/*y==fa[x]||*/y==son[x]) continue; top[y]=y; dfs2(y); } } void bui(int o,int l,int r) { if(l==r) {z1[o]=sz[b[l]]%mod,z2[o]=(z1[o]*z1[o])%mod,s1[o]=a[b[l]]*z1[o]%mod,s2[o]=a[b[l]]*z2[o]%mod;return;} bui(lc,l,mid),bui(rc,mid+1,r); psup(o); z1[o]=(z1[lc]+z1[rc])%mod,z2[o]=(z2[lc]+z2[rc])%mod; } int n,q,x,y,z; char cc[4]; int main() { n=rd(),q=rd(); for(int i=2;i<=n;i++) { fa[i]=rd(),a[i]=rd()%mod; add(fa[i],i,a[i]); } dfs1(1),top[1]=1,dfs2(1); bui(1,1,n); while(q--) { scanf("%s",cc); if(cc[0]=='I') { x=rd(),y=rd(),z=rd()%mod; while(top[x]!=top[y]) { if(de[top[x]]<de[top[y]]) swap(x,y); modif(1,1,n,id[top[x]],id[x],z); x=fa[top[x]]; } if(de[x]>de[y]) swap(x,y); if(x!=y) modif(1,1,n,id[x]+1,id[y],z); } else { x=rd(); if(sz[x]==1) puts("0"); else printf("%d\n",((sz[x]%mod*quer1(1,1,n,id[x]+1,id[x]+sz[x]-1))%mod-quer2(1,1,n,id[x]+1,id[x]+sz[x]-1)+mod)%mod); } } return 0; }
Wannafly挑戰賽21 E 未來城市規劃