zoukankan      html  css  js  c++  java
  • BZOJ 4034: [HAOI2015]树上操作 [欧拉序列 线段树]

    题意:

    操作 1 :把某个节点 x 的点权增加 a 。

    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。

    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。


    显然树链剖分可做,但我是来练欧拉序列的

    和splay维护一样了

    其实没大有意义....如果树形态不改变人家树链剖分本来就可以维护子树信息....

    唯一的好处就是不会爆栈吧

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define lc x<<1
    #define rc x<<1|1
    #define mid ((l+r)>>1)
    #define lson lc, l, mid
    #define rson rc, mid+1, r
    #define pii pair<int, int>
    #define MP make_pair
    #define fir first
    #define sec second
    typedef long long ll;
    const int N=2e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    
    int n, Q, op, x, y, a[N];
    struct edge{int v, ne;} e[N<<1];
    int cnt, h[N];
    inline void ins(int u, int v) {
        e[++cnt]=(edge){v, h[u]}; h[u]=cnt;
        e[++cnt]=(edge){u, h[v]}; h[v]=cnt;
    }
    pii dfn[N]; int dfc, eul[N];
    void dfs(int u, int fa) {
        dfn[u].fir = ++dfc; eul[dfc] = u;
        for(int i=h[u]; i; i=e[i].ne) if(e[i].v != fa) dfs(e[i].v, u);
        dfn[u].sec = ++dfc; eul[dfc] = -u;
    }
    
    struct SegTre {
        struct meow{ll sum, tag; int sl, sr;} t[N<<2];
        inline void merge(int x) { 
            t[x].sum = t[lc].sum + t[rc].sum; 
            t[x].sl = t[lc].sl + t[rc].sl;
            t[x].sr = t[lc].sr + t[rc].sr;
        }
        inline void paint(int x, ll v) {
            t[x].sum += (t[x].sl - t[x].sr)*v;
            t[x].tag += v;
        }
        inline void pushDown(int x) {
            if(t[x].tag) {
                paint(lc, t[x].tag);
                paint(rc, t[x].tag);
                t[x].tag = 0;
            }
        }
        void build(int x, int l, int r) {
            if(l==r) {
                if(eul[l] > 0) t[x].sum = a[eul[l]], t[x].sl = 1;
                else t[x].sum = -a[-eul[l]], t[x].sr = 1;
            }else {
                build(lson);
                build(rson);
                merge(x);
            }
        }
    
        void Add(int x, int l, int r, int p, int v) {
            if(l==r) paint(x, v);
            else {
                pushDown(x);
                if(p<=mid) Add(lson, p, v);
                else Add(rson, p, v);
                merge(x);
            }
        }
        void Add2(int x, int l, int r, int ql, int qr, ll v) {
            if(ql<=l && r<=qr) paint(x, v);
            else {
                pushDown(x);
                if(ql<=mid) Add2(lson, ql, qr, v);
                if(mid<qr) Add2(rson, ql, qr, v);
                merge(x);
            }
        }
        ll Que(int x, int l, int r, int ql, int qr) {
            if(ql<=l && r<=qr) return t[x].sum;
            else {
                pushDown(x);
                ll ans=0;
                if(ql<=mid) ans += Que(lson, ql, qr);
                if(mid<qr)  ans += Que(rson, ql, qr);
                return ans;
            }
        }
    }seg;
    int main() {
        freopen("in","r",stdin);
        n=read(); Q=read();
        for(int i=1; i<=n; i++) a[i]=read();
        for(int i=1; i<n; i++) x=read(), y=read(), ins(x, y);
        dfs(1, 0); seg.build(1, 1, dfc);
        for(int i=1; i<=Q; i++) {
            op=read(); x=read(); 
            if(op==3) printf("%lld
    ", seg.Que(1, 1, dfc, dfn[1].fir, dfn[x].fir));
            else{
                y=read();
                if(op==1) seg.Add(1, 1, dfc, dfn[x].fir, y), seg.Add(1, 1, dfc, dfn[x].sec, y);
                else seg.Add2(1, 1, dfc, dfn[x].fir, dfn[x].sec, y);
            }
        }
    }
  • 相关阅读:
    haslayout详解
    linux定时任务-cron
    linux安装SVN
    linux java配置
    KVM virsh常用命令篇
    KVM创建虚拟机
    KVM和远程管理工具virt-manager
    mysql 基础命令
    json在线工具
    mvn简单命令
  • 原文地址:https://www.cnblogs.com/candy99/p/6591738.html
Copyright © 2011-2022 走看看