zoukankan      html  css  js  c++  java
  • BZOJ 4034 HAOI2015 树上操作

    4034: [HAOI2015]树上操作

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 6033  Solved: 1959
    [Submit][Status][Discuss]

    Description

    有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
    操作,分为三种:
    操作 1 :把某个节点 x 的点权增加 a 。
    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

    Input

    第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1 
    行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。再接下来 M 行,每行分别表示一次操作。其中
    第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
     

    Output

    对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

     

    Sample Input

    5 5
    1 2 3 4 5
    1 2
    1 4
    2 3
    2 5
    3 3
    1 2 1
    3 5
    2 1 2
    3 3

    Sample Output

    6
    9
    13

    HINT

     对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。

    Source

    鸣谢bhiaibogf提供

    网上大部分都是裸的树剖,其实可以用dfs序+线段树来写

    dfs序就不说了,处理出来进栈时间和出栈时间

    对于1操作就是在进栈时间对应线段树上的那个点加上v,在出栈时间对应线段树上的那个点减v

    对于2操作就是在x进栈时间在线段树上对应的那个点和出栈时间在线段树上对应的那个点之间的区间中,是进栈时间的就加上v就是出栈时间的就减去v

    这个我们用一个flag辅助数组来写,flag为1表示是进栈时间,flag为-1表示是出栈时间

    第三个操作我们直接查询1到x进栈时间在线段树上对应那个点的区间和即可

    具体实现看代码

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    inline ll read(){
        ll x=0;ll f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const ll MAXN=1e6+10;
    struct node{
        ll y,next;
    }e[MAXN];
    ll linkk[MAXN],len=0,n,m,in[MAXN],out[MAXN],dfs_clock=0,a[MAXN],b[MAXN],mk[MAXN];
    inline void insert(ll xx,ll yy){
        e[++len].y=yy;e[len].next=linkk[xx];linkk[xx]=len;
    }
    inline void dfs(ll st,ll father){
        in[st]=++dfs_clock;
        mk[dfs_clock]=1;b[dfs_clock]=a[st];
        for(ll i=linkk[st];i;i=e[i].next){
            if(e[i].y!=father){
                dfs(e[i].y,st);
            }
        }
        out[st]=++dfs_clock;mk[dfs_clock]=-1;b[dfs_clock]=a[st];
    }
    void init(){
        n=read();m=read();
        for(ll i=1;i<=n;i++){
            a[i]=read();
        }
        for(ll i=1;i<n;i++){
            ll xx=read();ll yy=read();
            insert(xx,yy);insert(yy,xx);
        }
        dfs(1,0);
    }
    struct Tree{
        ll delta,sum,flag;
    }T[MAXN<<1];
    ll x,y,v;
    inline void push_down(ll root){
        ll del=T[root].delta;
        T[root<<1].delta+=del;T[root<<1|1].delta+=del;
        T[root<<1].sum+=del*T[root<<1].flag;T[root<<1|1].sum+=del*T[root<<1|1].flag;
        T[root].delta=0;
    }
    inline void build(ll l,ll r,ll root){
        T[root].sum=T[root].delta=0;
        ll mid=(l+r)>>1;
        if(l==r){
            T[root].sum=mk[l]*b[l];
            T[root].flag=mk[l];
            return;
        }
        build(l,mid,root<<1);
        build(mid+1,r,root<<1|1);
        T[root].flag=T[root<<1].flag+T[root<<1|1].flag;
        T[root].sum=T[root<<1].sum+T[root<<1|1].sum;
    }
    inline void insert1(ll l,ll r,ll root){
        if(l>x||r<x) return;
        if(l==r){
            T[root].sum+=T[root].flag*y;
            T[root].delta+=y;
            return;
        }
        ll mid=(l+r)>>1;
        if(T[root].delta) push_down(root);
        insert1(l,mid,root<<1);
        insert1(mid+1,r,root<<1|1);
        T[root].sum=T[root<<1].sum+T[root<<1|1].sum;
    }
    inline void insert2(ll l,ll r,ll root){
        if(l>y||r<x) return;
        if(l>=x&&r<=y){
            T[root].sum+=T[root].flag*v;T[root].delta+=v;
            return;
        }
        ll mid=(l+r)>>1;
        if(T[root].delta) push_down(root);
        insert2(l,mid,root<<1);
        insert2(mid+1,r,root<<1|1);
        T[root].sum=T[root<<1].sum+T[root<<1|1].sum;
    }
    inline ll query(ll l,ll r,ll root){
        if(l>y||r<x) return 0;
        if(l>=x&&r<=y) return T[root].sum;
        ll mid=(l+r)>>1;
        if(T[root].delta) push_down(root);
        return query(l,mid,root<<1)+query(mid+1,r,root<<1|1);
    }
    void solve(){
        build(1,dfs_clock,1);
        for(ll i=1;i<=m;i++){
            ll op=read();
            if(op==1){
                ll t=read();y=read();x=in[t];
                insert1(1,dfs_clock,1);
                x=out[t];
                insert1(1,dfs_clock,1);
            }
            if(op==2){
                ll t=read();v=read();
                x=in[t];y=out[t];
                insert2(1,dfs_clock,1);
            }
            if(op==3){
                ll t=read();x=1;y=in[t];
                printf("%lld
    ",query(1,dfs_clock,1));
            }
        }
    }
    int main(){
        //freopen("All.in","r",stdin);
        //freopen("a.out","w",stdout);
        init();
        solve();
        return 0;
    }
    

      

  • 相关阅读:
    CodeForces 242E二维线段树
    树形DP
    014 国际化
    013 属性文件
    012 BeanPostProcessor
    011 aware
    010 依赖注入
    009 IOC--初始化和销毁
    008 IOC--Bean的作用域
    007 IOC---Resource
  • 原文地址:https://www.cnblogs.com/something-for-nothing/p/7896097.html
Copyright © 2011-2022 走看看