bzoj4034 [HAOI2015]树上操作(树链剖分)

来源:互联网 发布:美瞳推荐知乎 编辑:程序博客网 时间:2024/05/24 06:09

子树修改,通过dfn序可以变成区间修改。然后就是裸题了。

#include<cstdio>#include<cstring>#define ll long long#define N 100010int n,a[N],m,num=0,h[N],dep[N],size[N],son[N],fa[N],top[N],in[N],out[N],dfn=0,w[N];struct edge{    int to,next;}data[N<<1];struct node{    ll lazy,sum;}tree[N<<2];inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}inline int max(int x,int y){return x>y?x:y;}inline ll max(ll x,ll y){return x>y?x:y;}void dfs1(int x){    size[x]=1;    for(int i=h[x];i;i=data[i].next){        int y=data[i].to;        if(fa[x]==y) continue;        fa[y]=x;dep[y]=dep[x]+1;dfs1(y);size[x]+=size[y];        if(size[y]>size[son[x]]) son[x]=y;    }}void dfs2(int x,int tp){    top[x]=tp;in[x]=++dfn;w[dfn]=a[x];    if(son[x]) dfs2(son[x],tp);    for(int i=h[x];i;i=data[i].next){        int y=data[i].to;        if(y==son[x]||y==fa[x]) continue;        dfs2(y,y);    }    out[x]=dfn;}inline void pushup(int p){    tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;}inline void pushdown(int p,int l,int r,int mid){    if(!tree[p].lazy) return;    tree[p<<1].lazy+=tree[p].lazy;tree[p<<1|1].lazy+=tree[p].lazy;    tree[p<<1].sum+=(mid-l+1)*tree[p].lazy;    tree[p<<1|1].sum+=(r-mid)*tree[p].lazy;    tree[p].lazy=0;}void build(int p,int l,int r){    if(l==r){tree[p].sum=w[l];return;}    int mid=l+r>>1;    build(p<<1,l,mid);build(p<<1|1,mid+1,r);    pushup(p);}void change(int p,int l,int r,int x,int y,ll v){//v也要longlong!!!坑死人。     if(x<=l&&r<=y){        tree[p].lazy+=v;tree[p].sum+=(r-l+1)*v;return;    }    int mid=l+r>>1;pushdown(p,l,r,mid);    if(x<=mid) change(p<<1,l,mid,x,y,v);    if(y>mid) change(p<<1|1,mid+1,r,x,y,v);    pushup(p);}ll qsum(int p,int l,int r,int x,int y){    if(x<=l&&r<=y) return tree[p].sum;    int mid=l+r>>1;pushdown(p,l,r,mid);ll sum=0;    if(x<=mid) sum+=qsum(p<<1,l,mid,x,y);    if(y>mid) sum+=qsum(p<<1|1,mid+1,r,x,y);    return sum;}ll query(int x){    ll sum=0;    while(top[x]!=1){        sum+=qsum(1,1,n,in[top[x]],in[x]);        x=fa[top[x]];    }    sum+=qsum(1,1,n,1,in[x]);    return sum;}int main(){//  freopen("a.in","r",stdin);    n=read();m=read();    for(int i=1;i<=n;++i) a[i]=read();    for(int i=1;i<n;++i){        int x=read(),y=read();        data[++num].to=y;data[num].next=h[x];h[x]=num;        data[++num].to=x;data[num].next=h[y];h[y]=num;    }    dep[1]=1;dfs1(1);dfs2(1,1);build(1,1,n);    while(m--){        int op=read(),x=read();        if(op==1) change(1,1,n,in[x],in[x],read());        if(op==2) change(1,1,n,in[x],out[x],read());        if(op==3) printf("%lld\n",query(x));    }    return 0;}