zoukankan      html  css  js  c++  java
  • bzoj4034: [HAOI2015]T2

    dfs序+线段树.

    首先生成树的出栈入栈序。

    然后入栈设为a[u],出栈设为-a[u]。

    子树在线段树上是一个连续的范围,所以三个操作都可以在线段树上实现了。

    ps:val设成int,wa了无数发。。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int maxn = 800000 + 10;
    const int maxm = 800000 + 10;
    const int maxk = 800000 + 10;
    
    int g[maxn],v[maxm],next[maxm],eid;
    int n,m,vid;
    int a[maxm],b[maxm];
    int in[maxn],out[maxn];
    bool down[maxn];
    //int id[maxn];
    
    void addedge(int a,int b) {
        v[eid]=b; next[eid]=g[a]; g[a]=eid++;
        v[eid]=a; next[eid]=g[b]; g[b]=eid++;
    }
    
    struct Segtree {
        #define lc(x) ((x)<<1)
        #define rc(x) (((x)<<1)|1)
        
        int l[maxk],r[maxk];
        LL sumv[maxk],addv[maxk];
        int flag[maxk];
        
        void push(int x) {
            if(!addv[x] || l[x]==r[x]) return;
            addv[lc(x)]+=addv[x];
            addv[rc(x)]+=addv[x];
            sumv[lc(x)]+=(flag[lc(x)])*addv[x];
            sumv[rc(x)]+=(flag[rc(x)])*addv[x];
            addv[x]=0;
        }
        
        inline void update(int x) {
            sumv[x]=sumv[lc(x)]+sumv[rc(x)];
        }
        
        void add(int x,int L,int R,LL val) {
            if(R<l[x] || L>r[x]) return;
            if(L<=l[x] && r[x]<=R) {
                sumv[x]+=(flag[x]*val);
                addv[x]+=val;    
                return;
            }
            push(x);
            add(lc(x),L,R,val);
            add(rc(x),L,R,val);
            update(x);
        }
        
        LL query(int x,int L,int R) {
            if(R<l[x] || L>r[x]) return 0;
            if(L<=l[x] && r[x]<=R) return sumv[x];
            push(x);
            return (query(lc(x),L,R)+query(rc(x),L,R));
        }
        
        void build(int x,int L,int R) {
            l[x]=L; r[x]=R;
            if(L==R) {
                sumv[x]=a[L];
                addv[x]=0;
                if(down[L]) flag[x]=1;
                else flag[x]=-1;    
                return;
            }
            int mid=(L+R)>>1;
            build(lc(x),L,mid);
            build(rc(x),mid+1,R);
            update(x);
            flag[x]=flag[lc(x)]+flag[rc(x)];        
        }
        
    }seg;
    
    void dfs(int u,int from) {
        a[++vid]=b[u]; down[vid]=1;
        in[u]=vid;
        for(int i=g[u];~i;i=next[i]) if(v[i]!=from) dfs(v[i],u);
        a[++vid]=-b[u];
        out[u]=vid;    down[vid]=0;
    }
    
    int main() {
        memset(g,-1,sizeof(g));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&b[i]);
        for(int i=1,x,y;i<n;i++) {
            scanf("%d%d",&x,&y);
            addedge(x,y);
        }
        dfs(1,0);
        seg.build(1,1,(n<<1));
        int p,x,a;
        while(m--) {
            scanf("%d",&p);
            if(p==1) {
                scanf("%d%d",&x,&a);
                seg.add(1,in[x],in[x],a);
                seg.add(1,out[x],out[x],a);
            }
            else if(p==2) {
                scanf("%d%d",&x,&a);
                seg.add(1,in[x],out[x],a);
            }
            else {
                scanf("%d",&x);
                printf("%lld
    ",seg.query(1,1,in[x]));
            }
        }
        return 0;
    }

  • 相关阅读:
    Perl的运算符号字符
    windows xp 使用远程桌面时的关机/重新启动方法
    抵御TCP的洪水
    远程桌面连接中的常见问题 连接上就断开
    批量kill mysql进程
    Linux如何查看硬盘型号和缓存
    Apache Rewrite 规则详解
    nginx 内置变量大全
    大数据量分页存储过程效率测试附代码
    ASP.Net 更新页面输出缓存的几种方法(包括用户控件,iframe,页面缓存等)
  • 原文地址:https://www.cnblogs.com/invoid/p/5625945.html
Copyright © 2011-2022 走看看