BZOJ4034_树上操作_KEY

题目传送门

这道题可以树链剖分+线段树。

其他操作模板,第二个操作只需要将x~x+size[x]-1区间加值即可。

code:

#include <cstdio>
#include <cstring>
using namespace std;

int read(){
    char c;while(c=getchar(),(c<'0'||c>'9')&&c!='-');
    int x=0,y=1;c=='-'?y=-1:x=c-'0';
    while(c=getchar(),c>='0'&&c<='9')x=x*10+c-'0';
    return x*y;
}

const int Maxn=100005;

int N,Q,A[Maxn];
int head[Maxn],nxt[Maxn<<1],to[Maxn<<1],Cnt;
void Add(int x,int y){
    to[Cnt]=y;
    nxt[Cnt]=head[x];
    head[x]=Cnt;
    Cnt++;
}

int Son[Maxn],Size[Maxn],f[Maxn];
int Dep[Maxn],Dfn[Maxn],Top[Maxn];
int C;
void Find(int Now,int Deep,int Bef){
    
    f[Now]=Bef,Dep[Now]=Deep,Size[Now]=1;
        for(int i=head[Now];i!=-1;i=nxt[i]){
            if(to[i]==f[Now])continue;
            Find(to[i],Deep+1,Now);
            Size[Now]+=Size[to[i]];
            if(Size[to[i]]>Size[Son[Now]])
                Son[Now]=to[i];
        }
    return ;
}
void Fs(int Now,int Tp){
    Dfn[Now]=++C,Top[Now]=Tp;
    if(Son[Now])Fs(Son[Now],Tp);
        for(int i=head[Now];i!=-1;i=nxt[i]){
            if(to[i]==Son[Now]||to[i]==f[Now])continue;
            Fs(to[i],to[i]);
        }
    return ;
}

long long Seg[Maxn<<2],Ade[Maxn<<2];
void Up(int x){Seg[x]=Seg[x<<1]+Seg[x<<1|1];}
void Down(int x,long long l,long long r){
    if(!Ade[x])return ;
    Seg[x<<1]+=Ade[x]*l;
    Seg[x<<1|1]+=Ade[x]*r;
    Ade[x<<1]+=Ade[x];
    Ade[x<<1|1]+=Ade[x];
    Ade[x]=0;
}
void Updata(int Node,int L,int R,int Ul,int Ur,long long Val){
    if(Ul<=L&&Ur>=R){
        Seg[Node]+=Val*(R-L+1);
        Ade[Node]+=Val;
        return ;
    }
    int Mid=L+R>>1;
    Down(Node,Mid-L+1,R-Mid);
    if(Mid>=Ul)Updata(Node<<1,L,Mid,Ul,Ur,Val);
    if(Mid< Ur)Updata(Node<<1|1,Mid+1,R,Ul,Ur,Val);
    Up(Node);
}
long long Query(int Node,int L,int R,int Ql,int Qr){
    if(Ql<=L&&Qr>=R)return Seg[Node];
    int Mid=L+R>>1;
    Down(Node,Mid-L+1,R-Mid);
    long long Ans=0;
    if(Mid>=Ql)Ans+=Query(Node<<1,L,Mid,Ql,Qr);
    if(Mid< Qr)Ans+=Query(Node<<1|1,Mid+1,R,Ql,Qr);
    return Ans;
}
long long G(int Node){
    long long Ans=0;
        while(Top[Node]){
            Ans+=Query(1,1,N,Dfn[Top[Node]],Dfn[Node]);
            Node=f[Top[Node]];
        }
    return Ans;
}

int main()
{
    memset(head,-1,sizeof head);
    N=read(),Q=read();
        for(int i=1;i<=N;i++)A[i]=read();
        for(int i=1;i<N;i++){
            int x=read(),y=read();
            Add(x,y),Add(y,x);
        }
    Find(1,1,0),Fs(1,1);
        for(int i=1;i<=N;i++)
            Updata(1,1,N,Dfn[i],Dfn[i],A[i]);
        for(int i=1;i<=Q;i++){
            int Type=read(),x=read();
            if(Type==1)Updata(1,1,N,Dfn[x],Dfn[x],read());
            if(Type==2)Updata(1,1,N,Dfn[x],Dfn[x]+Size[x]-1,read());
            if(Type==3)printf("%lld\n",G(x));
        }
    return 0;
}

 

posted @ 2018-03-20 07:33  Cptraser  阅读(150)  评论(0编辑  收藏  举报