• [HAOI2015]树上操作


    题目描述

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

    输入输出格式

    输入格式:

    第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1 行每行两个正整数 from, to , 表示该树中存在一条边 (from, to) 。再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

    输出格式:

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

    输入输出样例

    输入样例#1:

    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

    输出样例#1:

    6 9 13 对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不

    会超过 10^6 。

    solution

    树链剖分裸题没什么好说的。。。

    对于操作1,线段树单点修改

    操作2,区间修改

    操作3,相当于求节点1,到节点x这条链上的和。

    然而求这么简单一道题,我还提交了8遍。。。

    主要是细节:

    1.把建树的1打成了l。

    2.把查询中的这个

     if(dep[tx]>dep[ty])
            {
                swap(x,y);
                swap(tx,ty);
            }

    写成了这样

     if(dep[x]>dep[y])
            {
                swap(x,y);
                swap(tx,ty);
            }

    3.把一个+=写成了=

    4.单点修改没有管懒标记。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 100000 + 10;
    inline int read()
    {
        char ch;
        int fl=1;
        int xx=0;
        do{
          ch= getchar();
          if(ch=='-')
            fl=-1;
        }while(ch<'0'||ch>'9');
        do{
            xx=(xx<<3)+(xx<<1)+ch-'0';
            ch=getchar();
        }while(ch>='0'&&ch<='9');
        return xx*fl;
    }
    int n,m;
    int a[MAXN];
    struct node
    {
        int to;
        int next;
    };node g[MAXN*2];
    int fa[MAXN],head[MAXN],dep[MAXN],tot[MAXN],son[MAXN],cnt=0;
    inline void addedge(int x,int y){
        ++cnt;g[cnt].to=y;g[cnt].next=head[x];head[x]=cnt;return;
    }
    inline void dfs(int x)
    {
        tot[x]=1,son[x]=0;
        for(int i=head[x];i>0;i=g[i].next)
        {
            int v=g[i].to;
            if(v!=fa[x])
            {
                dep[v]=dep[x]+1;
                fa[v]=x;
                dfs(v);
                if(tot[v]>tot[son[x]]) son[x]=v;
                tot[x]+=tot[v];
            }
        }
        return;
    }
    int num[MAXN],top[MAXN],z=0;
    inline void dfs2(int now,int t)
    {
        top[now]=t;++z;num[now]=z;
        if(son[now]) dfs2(son[now],t);
        for(int i=head[now];i>0;i=g[i].next)
        {
            int v=g[i].to;
            if(v!=son[now]&&v!=fa[now])
            dfs2(v,v);
        }
    }
    struct TREE
    {
        int l;
        int r;
        long long sum;
        inline int mid(){
            return    (l+r)>>1;
        }
    }tree[MAXN*4];
    long long add[MAXN*4];
    #define lc o<<1
    #define rc o<<1|1
    inline void build(int o,int l,int r)
    {
        tree[o].l=l;tree[o].r=r;
        int  mid=tree[o].mid();
        if(l==r) {
            tree[o].sum=0;
            return;
        }
        else
        {
            build(lc,l,mid);
            build(rc,mid+1,r);
            tree[o].sum=tree[lc].sum+tree[rc].sum;
        } 
    }
    
    inline void pushup(int o)
    {
        add[lc]+=add[o];
        add[rc]+=add[o];
        tree[lc].sum+=(tree[lc].r-tree[lc].l+1)*add[o];
        tree[rc].sum+=(tree[rc].r-tree[rc].l+1)*add[o];
        add[o]=0;
    }
    
    inline void change(int o,int x,int y)
    {
        int l=tree[o].l,r=tree[o].r;
        int mid=tree[o].mid();
        if(l==r)
        {
            tree[o].sum+=y;
            return;
        }
        else
        {
            pushup(o);
            if(x>=mid+1) change(rc,x,y);
            else change(lc,x,y);
            tree[o].sum=tree[lc].sum+tree[rc].sum;
        }
    }
    
    inline void change2(int o,int x,int y,long long z)
    {
        int l=tree[o].l,r=tree[o].r;
        if(x<=l&&y>=r)
        {
            add[o]+=z;
            tree[o].sum+=(tree[o].r-tree[o].l+1)*z;
            return;
        }
        else if(l>y||x>r) return ;
        else
        {
            if(add[o])
            pushup(o);
            change2(lc,x,y,z);
            change2(rc,x,y,z);
            tree[o].sum=tree[lc].sum+tree[rc].sum;
            return;
        }    
    } 
    inline long long query(int o,int x,int y)
    {
        int l=tree[o].l,r=tree[o].r;
        if(x<=l&&y>=r)
        {
            return tree[o].sum;
        }
        else if(l>y||x>r) return 0;
        else
        {
            if(add[o])
            pushup(o);
            return query(lc,x,y)+query(rc,x,y);
        }        
    } 
    inline long long query_sum(int x,int y)
    {
        int tx=top[x],ty=top[y];
        long long ans=0;
        while(tx!=ty)
        {
            if(dep[tx]>dep[ty])
            {
                swap(x,y);
                swap(tx,ty);
            }
            ans+=query(1,num[ty],num[y]);
            y=fa[ty];ty=top[y];
        }
        if(dep[x]>dep[y])
        {
            swap(x,y);
        }
        ans+=query(1,num[x],num[y]);
        return ans;
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++) a[i]=read(),head[i]=-1;
        for(int i=1;i<n;i++)
        {
            int x,y;
            x=read();
            y=read();
            addedge(x,y);
            addedge(y,x);
        }
        fa[1]=0;dep[1]=1;dfs(1);
        dfs2(1,1);
        build(1,1,z);
        for(int i=1;i<=n;i++) 
        change(1,num[i],a[i]);
        for(int i=1;i<=m;i++)
        {
            long long op,x,y;
            op=read();
            if(op==1)
            {
                x=read(),y=read();
                change(1,num[x],y);
            }
            if(op==2)
            {
                x=read();y=read();
                change2(1,num[x],num[x]+tot[x]-1,y);
            }
            if(op==3)
            {
                x=read();
                printf("%lld
    ",query_sum(1,x));
            }
        }
            return 0;
    }
  • 相关阅读:
    UICollectionView中使用 UICollectionViewFlowLayout进行布局(模仿苹果相册)
    使用CocoaPods被卡住:Updating local specs repositories
    【原】iOS 同时重写setter和getter时候报错:Use of undeclared identifier '_name';did you mean 'name'
    iOS 设置不同的字体颜色
    使用java代码,动态给TextView设置drawable
    格式化浮点数(保留指定位数)
    监听输入法的出现和隐藏
    dp和px的转换
    获取状态栏高度
    获取在attr.xml中声明的主题样式
  • 原文地址:https://www.cnblogs.com/wlzs1432/p/8868992.html
Copyright © 2020-2023  润新知