• BZOJ 4034[HAOI2015]树上操作 树链剖分


    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

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

    题解:刷水有益健康...

    #include <bits/stdc++.h>
    #define setIO(s) freopen(s".in","r",stdin), freopen(s".out","w",stdout)  
    #define maxn 110000 
    #define ll long long 
    #define lson (x<<1)
    #define rson ((x<<1)|1)
    using namespace std;
    int hd[maxn], to[maxn << 1], nex[maxn << 1], st[maxn], ed[maxn]; 
    int fa[maxn], dep[maxn], dfn[maxn], ln[maxn], hson[maxn], siz[maxn], bot[maxn], top[maxn];  
    int edges, n , Q, tim; 
    ll val[maxn]; 
    void add(int u, int v)
    {
        nex[++edges] = hd[u], hd[u] = edges, to[edges] = v; 
    }  
    void dfs1(int u, int ff)
    {
        fa[u] = ff, dep[u] = dep[ff] + 1, siz[u] = 1; 
        for(int i = hd[u]; i ; i = nex[i])
        {
            int v = to[i]; 
            if(v == ff) continue; 
            dfs1(v, u); 
            siz[u] += siz[v]; 
            if(siz[v] > siz[hson[u]]) hson[u] = v; 
        }
    }
    void dfs2(int u, int tp)
    {
        top[u] = tp, ln[++tim] = u, dfn[u] = tim, st[u] = tim; 
        if(hson[u]) 
            dfs2(hson[u], tp), bot[u] = bot[hson[u]]; 
        else 
            bot[u] = u; 
        for(int i = hd[u]; i ; i = nex[i])
        {
            int v = to[i]; 
            if(v == fa[u] || v == hson[u]) continue; 
            dfs2(v, v); 
        }
        ed[u] = tim; 
    }
    struct Node
    {
        ll lazy, val, sumv;  
    }t[maxn << 3]; 
    void mark(int l, int r, int x, ll d)
    {
        t[x].lazy += d; 
        ll tmp = r - l + 1; 
        t[x].sumv += 1ll*tmp*1ll*d;       
    }
    void pushdown(int l, int r, int x)
    { 
        if(!t[x].lazy) return; 
        int mid = (l + r) >> 1; 
        if(mid >= l) mark(l, mid, lson, t[x].lazy); 
        if(r > mid)  mark(mid + 1, r, rson, t[x].lazy); 
        t[x].lazy = 0; 
    }
    void build(int l, int r, int x)
    {
        if(l == r)
        {
            t[x].sumv = t[x].val = val[ln[l]]; 
            return; 
        }
        int mid = (l + r) >> 1; 
        build(l, mid, lson); 
        build(mid + 1, r, rson); 
        t[x].sumv = t[lson].sumv + t[rson].sumv; 
    }
    void update(int l, int r, int x, int L, int R, ll d)
    {
        pushdown(l, r, x); 
        if(l >= L && r <= R) 
        {
            mark(l, r, x, d); 
            return;
        }
        int mid = (l + r) >> 1;
        if(L <= mid) update(l, mid, lson, L, R, d); 
        if(R > mid) update(mid + 1, r, rson, L, R, d); 
        t[x].sumv = t[lson].sumv + t[rson].sumv; 
    }
    ll query(int l, int r, int x, int L, int R)
    {
        pushdown(l, r, x); 
        if(l >= L && r <= R) return t[x].sumv; 
        int mid = (l + r) >> 1; 
        ll tmp = 0;
        if(L <= mid) tmp += query(l, mid, lson, L, R); 
        if(R > mid) tmp += query(mid + 1, r, rson, L, R); 
        return tmp;  
    }
    void modify1(int x, ll d)
    {
        update(1, n, 1, dfn[x], dfn[x], d); 
    }
    void modify2(int x, ll d)
    {
        update(1, n, 1, st[x], ed[x], d); 
    }
    ll Query(int x)
    {
        ll tmp = 0; 
        while(x) 
        {
            tmp += query(1, n, 1, dfn[top[x]], dfn[x]); 
            x = fa[top[x]]; 
        }
        return tmp; 
    }
    int main()
    {
        // setIO("input"); 
        scanf("%d%d",&n,&Q); 
        for(int i = 1;i <= n; ++i) scanf("%lld",&val[i]); 
        for(int i = 1, u , v; i < n; ++i) 
        {
            scanf("%d%d",&u,&v), add(u, v), add(v, u); 
        }
        dfs1(1, 0), dfs2(1, 1), build(1, n, 1); 
        while(Q--)
        {
            int opt, x; 
            ll a; 
            scanf("%d",&opt); 
            if(opt == 1)
            {
                scanf("%d%lld",&x,&a), modify1(x, a); 
            }
            if(opt == 2)
            {
                scanf("%d%lld",&x,&a), modify2(x, a); 
            }
            if(opt == 3)
            { 
                scanf("%d",&x); 
                printf("%lld
    ",Query(x)); 
            }
        }
        return 0; 
    }
    

      

  • 相关阅读:
    对于“口袋精灵”单元测试
    12-17:项目进度
    12-15:项目进度
    12-14:项目进度
    12-13:项目进度
    12-12:项目进度
    12-11:项目进度
    12-10:项目进度
    12-9:项目进度
    12-6:项目进度
  • 原文地址:https://www.cnblogs.com/guangheli/p/10981714.html
Copyright © 2020-2023  润新知