bzoj4034[HAOI2015]T2
题意:
N点树,以点 1 为根,且树点有边权。三种操作:把某个节点点权增加 a 、某个节点为根的子树中所有点的点权都增加 a 、询问某个节点到根的路径中所有点的点权和。
题解:
本题链剖可过。第二个操作只要每次在构造链的时候找到子树中在链中位置最大的节点,然后区间修改就行。听说正解是DFS序,不过我不会。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define inc(i,j,k) for(int i=j;i<=k;i++) 5 #define maxn 200000 6 #define ll long long 7 using namespace std; 8 9 struct e{int t,n;}; e es[maxn]; int ess,g[maxn]; 10 void pe(int f,int t){es[++ess]=(e){t,g[f]}; g[f]=ess; es[++ess]=(e){f,g[t]}; g[t]=ess;} 11 int l[maxn*4],r[maxn*4],ch[maxn*4][2],fa[maxn],dep[maxn],pos[maxn],top[maxn],sz[maxn],sgs,mx[maxn]; 12 ll v[maxn][2],sm[maxn*4],tg[maxn*4]; 13 void dfs(int x){ 14 sz[x]=1; for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa[x]){ 15 fa[es[i].t]=x; dep[es[i].t]=dep[x]+1; dfs(es[i].t); sz[x]+=sz[es[i].t]; 16 } 17 } 18 void buildchain(int x,int ps){ 19 pos[x]=mx[x]=++sgs; v[sgs][1]=v[x][0]; top[x]=ps; int mx1=0,mx2=0; 20 for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa[x]&&mx2<sz[es[i].t])mx2=sz[es[i].t],mx1=es[i].t; 21 if(mx1)buildchain(mx1,ps),mx[x]=max(mx[x],mx[mx1]); 22 for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa[x]&&es[i].t!=mx1) 23 buildchain(es[i].t,es[i].t),mx[x]=max(mx[x],mx[es[i].t]); 24 } 25 void pushdown(int x){ 26 if(x&&tg[x]){ 27 int lc=ch[x][0],rc=ch[x][1]; 28 if(lc)sm[lc]+=(r[lc]-l[lc]+1)*tg[x],tg[lc]+=tg[x]; 29 if(rc)sm[rc]+=(r[rc]-l[rc]+1)*tg[x],tg[rc]+=tg[x]; 30 tg[x]=0; 31 } 32 } 33 void build(int x,int L,int R){ 34 if(L==R)sm[x]=v[L][1],ch[x][0]=ch[x][1]=0,l[x]=r[x]=L;else{ 35 ch[x][0]=x<<1,l[x]=L,ch[x][1]=x<<1|1,r[x]=R; int M=(L+R)>>1; 36 build(ch[x][0],L,M); build(ch[x][1],M+1,R); sm[x]=sm[ch[x][0]]+sm[ch[x][1]]; 37 } 38 } 39 ll query(int x,int L,int R){ 40 pushdown(x); 41 if(L<=l[x]&&r[x]<=R)return sm[x];else{ 42 ll q=0;int M=(l[x]+r[x])>>1; if(L<=M)q+=query(ch[x][0],L,R); if(M<R)q+=query(ch[x][1],L,R); 43 return q; 44 } 45 } 46 void add(int x,int L,int R,ll val){ 47 pushdown(x); 48 if(L<=l[x]&&r[x]<=R)tg[x]+=val,sm[x]+=(r[x]-l[x]+1)*val;else{ 49 int M=(l[x]+r[x])>>1; if(L<=M)add(ch[x][0],L,R,val); if(M<R)add(ch[x][1],L,R,val); 50 sm[x]=sm[ch[x][0]]+sm[ch[x][1]]; 51 } 52 } 53 inline ll querysum(int x){ll q=0; while(x)q+=query(1,pos[top[x]],pos[x]),x=fa[top[x]]; return q;} 54 void init1(){ess=0; memset(g,0,sizeof(g));} 55 void init2(){dep[1]=fa[1]=0; dfs(1); sgs=0; buildchain(1,1); build(1,1,sgs);} 56 int n,m; 57 int main(){ 58 //freopen("test.txt","r",stdin); 59 scanf("%d%d",&n,&m); inc(i,1,n)scanf("%lld",&v[i][0]); init1(); 60 inc(i,1,n-1){int a,b; scanf("%d%d",&a,&b); pe(a,b);} init2(); 61 inc(i,1,m){ 62 int opt,x;ll y; scanf("%d%d",&opt,&x); 63 if(opt==1)scanf("%lld",&y),add(1,pos[x],pos[x],y); 64 if(opt==2)scanf("%lld",&y),add(1,pos[x],mx[x],y); 65 if(opt==3)printf("%lld\n",querysum(x)); 66 } 67 return 0; 68 }
20160425