[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
",x,a,b,l,r,v);
 54     if(l<=a&&r>=b){tag[x]+=v,sm[x]+=(ll)(b-a+1)*v;/*,printf("! %d
",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
",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
",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
",sum);
110         }
111     }
112     return 0;
113 }
View Code
原文地址:https://www.cnblogs.com/czllgzmzl/p/5308224.html