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;
    }
  • 相关阅读:
    STM32 F4 DAC DMA Waveform Generator
    STM32 F4 General-purpose Timers for Periodic Interrupts
    Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式
    Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 httplib模块 django和web服务器整合 wsgi模块 gunicorn模块
    查看SQL Server服务运行帐户和SQL Server的所有注册表项
    Pycharm使用技巧(转载)
    SQL Server 2014内存优化表的使用场景
    Python第十天 print >> f,和fd.write()的区别 stdout的buffer 标准输入 标准输出 从控制台重定向到文件 标准错误 重定向 输出流和输入流 捕获sys.exit()调用 optparse argparse
    Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数
    Python第六天 类型转换
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8316330.html
Copyright © 2011-2022 走看看