zoukankan      html  css  js  c++  java
  • [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 。


    比洛谷板子还简单。。。不解释了,应该都会吧


    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #define ll long long 
    using namespace std;
    struct node{
        ll to,next;
    }e[500001];
    ll head[500001],dep[500001],sum[500001],a[500001];
    ll tot,num,n,m,lazy[500001],fa[500001],l[500001];
    ll ch[500001],top[500001],size[500001],son[500001];
    void build(int root,int l,int r)
    {
        if(l==r){sum[root]=a[l];return ;}
        int mid=(l+r)>>1;
        build(root<<1,l,mid);
        build(root<<1|1,mid+1,r);
        sum[root]=sum[root<<1]+sum[root<<1|1];
        return ;
    }
    
    void push(int root,int l,int r)
    {
        int mid=(l+r)>>1;
        lazy[root<<1]+=lazy[root];
        lazy[root<<1|1]+=lazy[root];
        sum[root<<1]+=lazy[root]*(mid-l+1);
        sum[root<<1|1]+=lazy[root]*(r-mid);
        lazy[root]=0;
        return ;
    }
    
    void update(int root,int left,int right,int l,int r,ll k)
    {
        if(l<=left&&r>=right)
        {
        sum[root]+=k*(right-left+1);
        lazy[root]+=k;
        return;
        }
        if(left>r||right<l)return ;
        int mid=(left+right)>>1;
        if(lazy[root])push(root,left,right);
        if(mid>=l)update(root<<1,left,mid,l,r,k);
        if(mid<r) update(root<<1|1,mid+1,right,l,r,k);
        sum[root]=sum[root<<1|1]+sum[root<<1];
        return;
    }
    
    ll query(int root,int left,int right,int l,int r)
    {
        if(l<=left&&r>=right)return sum[root];
        if(left>r||right<l)return 0;
        int mid=(left+right)>>1;
        if(lazy[root])push(root,left,right);
        ll a=0,b=0;
        if(mid>=l) a=query(root<<1,left,mid,l,r);
        if(mid<r)  b=query(root<<1|1,mid+1,right,l,r);
        return a+b;
    }
    
    void dfs1(int x)
    {
        size[x]=1;
        for(int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            if(!dep[v])
            {
                dep[v]=dep[x]+1;
                fa[v]=x;
                dfs1(v);
                size[x]+=size[v];
                if(size[v]>size[son[x]])son[x]=v;
            }
            
        }
        return ;
    }
    
    void dfs2(int x,int t)
    {
        l[x]=++tot;a[tot]=ch[x];top[x]=t;
        
        if(son[x])dfs2(son[x],t);
        for(int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v!=fa[x]&&v!=son[x])
            dfs2(v,v);
        }
        return ;
    }
    
    ll cal(int x,int y)
    {
        ll maxx=0;
    
        int fx=top[x],fy=top[y];
        while(fx!=fy)
        {
            if(dep[fx]<dep[fy])
            {
                swap(x,y);swap(fx,fy);
            }
            maxx+=query(1,1,tot,l[fx],l[x]);
            x=fa[fx];
            fx=top[x];
    
        }
        if(l[x]>l[y])swap(x,y);
        maxx+=query(1,1,tot,l[x],l[y]);
        return maxx;
    }
    
    ll read()
    {
        ll x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    
    void add(int from,int to)
    {
        num++;
        e[num].to=to;
        e[num].next=head[from];
        head[from]=num;
    }
    int main()
    {
        n=read();m=read();
    
        for(int i=1;i<=n;i++)
        {
            ch[i]=read();
        }
        for(int i=1;i<n;i++)
        {
            int x,y;
            x=read();y=read();
            add(x,y);add(y,x);
        }
        dep[1]=1;
        fa[1]=1;
        dfs1(1);
    
        dfs2(1,1);
        build(1,1,n);
    
        for(int i=1;i<=m;i++)
        {
            int qwq;
            qwq=read();
            if(qwq==1)
            {
                ll x,y;
                x=read();y=read();
                update(1,1,tot,l[x],l[x],y);
            }
            if(qwq==2)
            {
                ll x,y;
                x=read();y=read();
                update(1,1,tot,l[x],l[x]+size[x]-1,y);
            }
    
            if(qwq==3)
            {
                int x;
                x=read();
                printf("%lld
    ",cal(x,1));
            }
       
        }
        return 0;
    }
  • 相关阅读:
    大数运算
    混合背包问题
    多重背包问题(二进制优化)
    完全背包
    01背包问题
    树状数组
    构建之法阅读笔记04
    第一次冲刺个人总结07
    构建之法阅读笔记03
    第一次冲刺个人总结06
  • 原文地址:https://www.cnblogs.com/hhh1109/p/8780609.html
Copyright © 2011-2022 走看看