zoukankan      html  css  js  c++  java
  • bzoj4034 [HAOI2015]树上操作

    4034: [HAOI2015]树上操作

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 6323  Solved: 2094
    [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序就可以了.
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const long long maxn = 200010;
    
    long long n,m,head[maxn],nextt[maxn],to[maxn],tot = 1,a[maxn],L[maxn << 2],R[maxn << 2],pos[maxn],ppos[maxn],fa[maxn];
    long long sizee[maxn],deep[maxn],top[maxn],son[maxn],cnt,endd[maxn];
    long long sum[maxn << 2],tag[maxn << 2];
    
    void add(long long x,long long y)
    {
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    void dfs(long long u,long long faa,long long dep)
    {
        sizee[u] = 1;
        deep[u] = dep;
        for (long long i = head[u];i;i = nextt[i])
        {
            long long v = to[i];
            if (v == faa)
                continue;
            fa[v] = u;
            dfs(v,u,dep + 1);
            sizee[u] += sizee[v];
            if (sizee[v] > sizee[son[u]])
                son[u] = v;
        }
    }
    
    void dfs2(long long u,long long topp)
    {
        top[u] = topp;
        pos[u] = ++cnt;
        ppos[cnt] = u;
        if (son[u])
            dfs2(son[u],topp);
        for (long long i = head[u];i;i = nextt[i])
        {
            long long v = to[i];
            if (v == fa[u] || v == son[u])
                continue;
            dfs2(v,v);
        }
        endd[u] = cnt;
    }
    
    void pushdown(long long o)
    {
        if (tag[o])
        {
            tag[o * 2] += tag[o];
            tag[o * 2 + 1] += tag[o];
            sum[o * 2] += tag[o] * (R[o * 2] - L[o * 2] + 1);
            sum[o * 2 + 1] += tag[o] * (R[o * 2 + 1] - L[o * 2 + 1] + 1);
            tag[o] = 0;
        }
    }
    
    void pushup(long long o)
    {
        sum[o] = sum[o * 2] + sum[o * 2 + 1];
    }
    
    void build(long long o,long long l,long long r)
    {
        L[o] = l;
        R[o] = r;
        if (l == r)
        {
            sum[o] = a[ppos[l]];
            return;
        }
        long long mid = (l + r) >> 1;
        build(o * 2,l,mid);
        build(o * 2 + 1,mid + 1,r);
        pushup(o);
    }
    
    void update(long long o,long long l,long long r,long long x,long long y,long long v)
    {
        if (x <= l && r <= y)
        {
            tag[o] += v;
            sum[o] += v * (r - l + 1);
            return;
        }
        pushdown(o);
        long long mid = (l + r) >> 1;
        if (x <= mid)
            update(o * 2,l,mid,x,y,v);
        if (y > mid)
            update(o * 2 + 1,mid + 1,r,x,y,v);
        pushup(o);
    }
    
    long long query(long long o,long long l,long long r,long long x,long long y)
    {
        if (x <= l && r <= y)
            return sum[o];
        pushdown(o);
        long long mid = (l + r) >> 1,res = 0;
        if (x <= mid)
            res += query(o * 2,l,mid,x,y);
        if (y > mid)
            res += query(o * 2 + 1,mid + 1,r,x,y);
        return res;
    }
    
    long long queryy(long long x)
    {
        long long res = 0;
        while (top[x] != 1)
        {
            res += query(1,1,n,pos[top[x]],pos[x]);
            x = fa[top[x]];
        }
        res += query(1,1,n,pos[1],pos[x]);
        return res;
    }
    
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for (long long i = 1; i <= n; i++)
            scanf("%lld",&a[i]);
        for (long long i = 1; i < n; i++)
        {
            long long x,y;
            scanf("%lld%lld",&x,&y);
            add(x,y);
            add(y,x);
        }
        dfs(1,0,1);
        dfs2(1,1);
        build(1,1,n);
        for (long long i = 1; i <= m; i++)
        {
            long long id,x,y;
            scanf("%lld",&id);
            if (id == 1)
            {
                scanf("%lld%lld",&x,&y);
                update(1,1,n,pos[x],pos[x],y);
            }
            if (id == 2)
            {
                scanf("%lld%lld",&x,&y);
                update(1,1,n,pos[x],endd[x],y);
            }
            if (id == 3)
            {
                scanf("%lld",&x);
                printf("%lld
    ",queryy(x));
            }
        }
    
        return 0;
    }
  • 相关阅读:
    网络编程前戏
    上传文件数据到数据库
    SpringMVC点滴(1)
    python全栈学习--day2
    python全栈学习--day1
    python练习册 每天一个小程序 第0013题
    python练习册 每天一个小程序 第0012题
    python练习册 每天一个小程序 第0011题
    [XMAN筛选赛](web)ctf用户登录
    python练习册 每天一个小程序 第0010题
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8316330.html
Copyright © 2011-2022 走看看