• bzoj 4034: 树上操作 线段树


    题目:

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

    题解:

    ysf : 树链剖分大水题 !
    lrd : 直接树剖不就好了嘛
    gls : 这树剖不行吗 ?
    lyc : ... ...

    本人表示,当时真的脑袋抽了,忘了树剖就能搞...
    但是我脑袋这么一抽就想出了一个(O(nlogn))的解法.

    我们处理出dfs序.

    如图:

    对应dfs序为:
    (1,2,3,-3,4,-4,-2,5,6,-6,-5,-1)
    然后对于所有的单点修改修改相应的入栈点和出栈点
    对于一个子树修改就修改左端点为入栈序,右端点为出栈序的区间
    对于一个查询就直接查询区间[1,入栈序]的权值和.

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(ll &x){
        x=0;char ch;bool flag = false;
        while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
        while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const ll maxn = 210010;
    struct Edge{
        ll to,next;
    }G[maxn<<1];
    ll head[maxn],cnt;
    inline void add(ll u,ll v){
        G[++cnt].to = v;
        G[cnt].next = head[u];
        head[u] = cnt;
    }
    #define v G[i].to
    ll ind[maxn],dfs_clock,oud[maxn],idx[maxn];
    void dfs(ll u,ll f){
        ind[u] = ++ dfs_clock;
        idx[dfs_clock] = u;
        for(ll i = head[u];i;i=G[i].next){
            if(v == f) continue;
            dfs(v,u);
        }
        oud[u] = ++ dfs_clock;
        idx[dfs_clock] = u;
    }
    #undef v
    struct Node{
        Node *ch[2];
        ll val,lazy;
        ll num1,num2;
        void update(){
            val = ch[0]->val + ch[1]->val;
            num1 = ch[0]->num1 + ch[1]->num1;
            num2 = ch[0]->num2 + ch[1]->num2;
        }
    }*null,mem[maxn<<2],*it,*root;
    inline void init(){
        it = mem;null = it++;
        null->ch[0] = null->ch[1] = null;
        null->val = null->lazy = null->num1 = null->num2 = 0;
        root = null;
    }
    inline Node* newNode(){
        Node *p = it++;p->ch[0] = p->ch[1] = null;
        return p;
    }
    inline void pushdown(Node *p){
        if(p == null || p->lazy == 0) return ;
        if(p->ch[0] != null){
            p->ch[0]->val += p->ch[0]->num1*p->lazy - p->ch[0]->num2*p->lazy;
            p->ch[0]->lazy += p->lazy;
        }
        if(p->ch[1] != null){
            p->ch[1]->val += p->ch[1]->num1*p->lazy - p->ch[1]->num2*p->lazy;
            p->ch[1]->lazy += p->lazy;
        }
        p->lazy = 0;
    }
    inline void insert(Node* &p,ll l,ll r,ll pos,ll val,ll ty){
        if(p == null) p = newNode();
        if(l == r){
            if(ty == 1) p->num1 = 1,p->num2 = 0;
            else if(ty == -1) p->num1 = 0,p->num2 = 1;
            p->val = p->num1*val - p->num2*val;
            return ;
        }
        ll mid = l+r >> 1;
        if(pos <= mid) insert(p->ch[0],l,mid,pos,val,ty);
        else insert(p->ch[1],mid+1,r,pos,val,ty);
        p->update();
    }
    inline void modify(Node *p,ll l,ll r,ll L,ll R,ll val){
        if(L <= l &&r <= R){
            p->lazy += val;
            p->val += p->num1*val - p->num2*val;
            return ;
        }
        pushdown(p);
        ll mid = l+r >> 1;
        if(L <= mid) modify(p->ch[0],l,mid,L,R,val);
        if(R >  mid) modify(p->ch[1],mid+1,r,L,R,val);
        p->update();
    }
    inline ll query(Node *p,ll l,ll r,ll L,ll R){
        if(L <= l && r <= R) return p->val;
        pushdown(p);ll mid = l+r >> 1;
        if(R <= mid) return query(p->ch[0],l,mid,L,R);
        if(L >  mid) return query(p->ch[1],mid+1,r,L,R);
        return query(p->ch[0],l,mid,L,R) + query(p->ch[1],mid+1,r,L,R);
    }
    ll c[maxn];
    int main(){init();
        ll n,m;read(n);read(m);
        for(ll i=1;i<=n;++i) read(c[i]);
        for(ll i=1,u,v;i<n;++i){
            read(u);read(v);
            add(u,v);add(v,u);
        }dfs(1,1);
        for(ll i=1;i<=n;++i){
            insert(root,1,dfs_clock,ind[i],c[i],1);
            insert(root,1,dfs_clock,oud[i],c[i],-1);
        }
        watch(root,1,dfs_clock);
        ll op,x,a;
        while(m--){
            read(op);
            if(op == 1){
                read(x);read(a);
                modify(root,1,dfs_clock,ind[x],ind[x],a);
                modify(root,1,dfs_clock,oud[x],oud[x],a);
            }else if(op == 2){
                read(x);read(a);
                modify(root,1,dfs_clock,ind[x],oud[x],a);
            }else if(op == 3){
                read(x);
                ll ans = query(root,1,dfs_clock,1,ind[x]);
                printf("%lld
    ",ans);
            }
        }
        getchar();getchar();
        return 0;
    }
    
  • 相关阅读:
    OpenStack开发基础-oslo.config
    对象的封装
    Oracle动态显示日志
    Marching squares &amp; Marching cubes
    Keil5.15使用GCC编译器链接.a库文件
    数据结构习题之树
    HDU 5358(2015多校联合训练赛第六场1006) First One (区间合并+常数优化)
    使用URL在线语音合成
    企业怎样高速搭建大数据处理系统
    http://blog.sina.com.cn/s/blog_7caae74b0100zl17.html
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6576231.html
Copyright © 2020-2023  润新知