[bzoj2836] 魔法树
俩操作:增加路径上的点的权值。查询子树的权值和。
想了想似乎只能树链剖分了。。好久没写链剖+数据结构了TAT
一开始没开LL炸了一发(明明有想到的。。我果然是傻逼= =
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 const int maxn=100233; 8 struct zs{ 9 int too,pre; 10 }e[maxn<<1];int tot,last[maxn]; 11 int lc[maxn<<1],rc[maxn<<1],tt; 12 ll sm[maxn<<1],tag[maxn<<1]; 13 int dfn[maxn],sz[maxn],fa[maxn],top[maxn],dep[maxn],tim; 14 int i,j,k,n,m,x,y,lca,v; 15 16 int ra;char rx; 17 inline int read(){ 18 rx=getchar(),ra=0; 19 while(rx<'0'||rx>'9')rx=getchar(); 20 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 21 } 22 23 24 inline void dfs1(int x){ 25 sz[x]=1,dep[x]=dep[fa[x]]+1; 26 for(int i=last[x];i;i=e[i].pre) 27 dfs1(e[i].too),sz[x]+=sz[e[i].too]; 28 } 29 inline void dfs2(int x,int chain){ 30 top[x]=chain,dfn[x]=++tim;int i,mx=0; 31 for(i=last[x];i;i=e[i].pre)if(sz[e[i].too]>sz[mx])mx=e[i].too; 32 if(!mx)return; 33 dfs2(mx,chain); 34 for(i=last[x];i;i=e[i].pre)if(e[i].too!=mx)dfs2(e[i].too,e[i].too); 35 } 36 inline int getlca(int a,int b){ 37 while(top[a]!=top[b]){ 38 if(dep[top[a]]<dep[top[b]])swap(a,b); 39 a=fa[top[a]]; 40 } 41 return dep[a]<dep[b]?a:b; 42 } 43 44 45 inline void insert(int a,int b){e[++tot].too=b,e[tot].pre=last[a],last[a]=tot;} 46 47 inline void pushdown(int x,int a,int b,int mid,int lc,int rc){ 48 tag[lc]+=tag[x],tag[rc]+=tag[x],sm[lc]+=tag[x]*(mid-a+1),sm[rc]+=tag[x]*(b-mid); 49 tag[x]=0; 50 } 51 #define upd(x) sm[x]=sm[lc[x]]+sm[rc[x]]; 52 inline void add(int x,int a,int b,int l,int r,int v){ 53 // printf("add:%d %d %d %d--%d %d\n",x,a,b,l,r,v); 54 if(l<=a&&r>=b){tag[x]+=v,sm[x]+=(ll)(b-a+1)*v;/*,printf("! %d\n",sm[x]);*/return;} 55 int mid=(a+b)>>1; 56 if(tag[x])pushdown(x,a,b,mid,lc[x],rc[x]); 57 if(l<=mid)add(lc[x],a,mid,l,r,v); 58 if(r>mid) add(rc[x],mid+1,b,l,r,v); 59 upd(x);//printf(" %d--%d %d %d %d\n",a,b,sm[x],sm[lc[x]],sm[rc[x]]); 60 } 61 inline ll query(int x,int a,int b,int l,int r){ 62 if(l<=a&&r>=b)return sm[x]; 63 int mid=(a+b)>>1; 64 if(tag[x])pushdown(x,a,b,mid,lc[x],rc[x]); 65 if(r<=mid)return query(lc[x],a,mid,l,r);else 66 if(l>mid)return query(rc[x],mid+1,b,l,r);else 67 return query(lc[x],a,mid,l,r)+query(rc[x],mid+1,b,l,r); 68 } 69 inline void build(int a,int b){ 70 tt++; 71 if(a==b)return; 72 int mid=(a+b)>>1,x=tt; 73 lc[x]=tt+1,build(a,mid),rc[x]=tt+1,build(mid+1,b); 74 } 75 76 77 inline void ADD(int x,int y,int v){ 78 while(top[x]!=top[y]){ 79 add(1,1,n,dfn[top[x]],dfn[x],v); 80 x=fa[top[x]]; 81 } 82 add(1,1,n,dfn[y],dfn[x],v); 83 } 84 /*inline ll QUERY(int x,int y){ 85 ll sum=0; 86 while(top[x]!=top[y]){ 87 sum+=query(1,1,n,dfn[top[x]],dfn[x]); 88 x=fa[top[x]]; 89 } 90 return sum+query(1,1,n,dfn[y],dfn[x]); 91 }*/ 92 93 94 int main(){ 95 n=read(); 96 for(i=1;i<n;i++)x=read()+1,y=read()+1,fa[y]=x,insert(x,y); 97 dfs1(1),dfs2(1,1); 98 build(1,n);char id; 99 for(m=read();m;m--){ 100 for(id=getchar();id<'A'||id>'Z';id=getchar()); 101 if(id=='A'){ 102 x=read()+1,y=read()+1,v=read(), 103 lca=getlca(x,y);//printf(" %d %d lca:%d\n",x,y,lca); 104 ADD(x,lca,v),ADD(y,lca,v),add(1,1,n,dfn[lca],dfn[lca],-v); 105 }else{ 106 x=read()+1; 107 //ll sum=QUERY(x,lca)+QUERY(y,lca)-query(1,1,n,dfn[lca],dfn[lca]); 108 ll sum=query(1,1,n,dfn[x],dfn[x]+sz[x]-1); 109 printf("%lld\n",sum); 110 } 111 } 112 return 0; 113 }