Wannafly挑战赛21 E 未来城市规划
https://www.nowcoder.com/acm/contest/159/E
数据结构好题orz
先看看一条边在一个子树里的贡献,就是这条边的权值×一边的点数×另一边的点数
设子树的树根是(x),这条边连接的深度较大的点是(y)。
那么贡献就是(W(siz_y)(siz_x-siz_y))
(W(siz_xsiz_y-siz_y^2))
边权放到点上,对每个点维护(Wsiz)和(Wsiz^2)即可。
注意nowcoder的clang++非常锅锅,尽量开全局变量,不然main里的n可能就随便从5变成67了(调了1h mmp)
#include<bits/stdc++.h>
#define il inline
#define vd void
#define mod 2019
typedef long long ll;
il int gi(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int W[50010];
int fir[50010],dis[50010],nxt[50010],id;
il vd link(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
int dfn[50010],redfn[50010],siz[50010],son[50010],dep[50010],fa[50010];
il vd dfs1(int x){
siz[x]=1;
for(int i=fir[x];i;i=nxt[i]){
dep[dis[i]]=dep[x]+1;
dfs1(dis[i]);
siz[x]+=siz[dis[i]];
if(siz[dis[i]]>siz[son[x]])son[x]=dis[i];
}
}
int top[50010];
il vd dfs2(int x,int tp){
dfn[x]=++dfn[0];redfn[dfn[0]]=x;
top[x]=tp;
if(son[x])dfs2(son[x],tp);
for(int i=fir[x];i;i=nxt[i])if(dis[i]!=son[x])dfs2(dis[i],dis[i]);
}
int s1[200010],s2[200010],S1[200010],S2[200100],lz[200010];
#define mid ((l+r)>>1)
il vd Inc(int x,const int&t){
S1[x]=(S1[x]+s1[x]*t)%mod;
S2[x]=(S2[x]+s2[x]*t%mod)%mod;
lz[x]=(lz[x]+t)%mod;
}
il vd down(const int&x){if(lz[x])Inc(x<<1,lz[x]),Inc(x<<1|1,lz[x]),lz[x]=0;}
il vd upd(const int&x){
S1[x]=S1[x<<1]+S1[x<<1|1];
S2[x]=S2[x<<1]+S2[x<<1|1];
}
il vd build(int x,int l,int r){
if(l==r){
int p=redfn[l];
s1[x]=siz[p],s2[x]=siz[p]*siz[p]%mod;
S1[x]=s1[x]*W[p]%mod,S2[x]=s2[x]*W[p]%mod;
return;
}
build(x<<1,l,mid),build(x<<1|1,mid+1,r);
upd(x);
s1[x]=(s1[x<<1]+s1[x<<1|1])%mod;
s2[x]=(s2[x<<1]+s2[x<<1|1])%mod;
}
il vd update(int x,int l,int r,const int&L,const int&R,const int&d){
if(L<=l&&r<=R)return Inc(x,d);
down(x);
if(L<=mid)update(x<<1,l,mid,L,R,d);
if(mid<R)update(x<<1|1,mid+1,r,L,R,d);
upd(x);
}
il std::pair<int,int> operator +(const std::pair<int,int>&a,const std::pair<int,int>&b){return std::make_pair(a.first+b.first,a.second+b.second);}
il std::pair<int,int> query(int x,int l,int r,const int&L,const int&R){
if(L<=l&&r<=R)return std::make_pair(S1[x],S2[x]);
down(x);
if(L<=mid)
if(mid<R)return query(x<<1,l,mid,L,R)+query(x<<1|1,mid+1,r,L,R);
else return query(x<<1,l,mid,L,R);
else return query(x<<1|1,mid+1,r,L,R);
}
int n,q;
int main(){
n=gi(),q=gi();
for(int i=2;i<=n;++i)fa[i]=gi(),W[i]=gi(),link(fa[i],i);
dfs1(1),dfs2(1,1);
build(1,1,n);
char opt[2];int u,v,w;
while(q--){
scanf("%s",opt);
if(opt[0]=='I'){
u=gi(),v=gi(),w=gi();
if(u==v)continue;
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]])update(1,1,n,dfn[top[u]],dfn[u],w),u=fa[top[u]];
else update(1,1,n,dfn[top[v]],dfn[v],w),v=fa[top[v]];
}
if(dfn[u]>dfn[v])std::swap(u,v);
update(1,1,n,dfn[u]+1,dfn[v],w);
}else{
w=gi();
if(siz[w]==1){puts("0");continue;}
std::pair<int,int>A=query(1,1,n,dfn[w]+1,dfn[w]+siz[w]-1);
A.first%=mod,A.second%=mod;
printf("%d
",(A.first*siz[w]-A.second+mod)%mod);
}
}
return 0;
}