[HAOI2015]T2

【题目描述】

有一棵点数为N的树,以点1为根,且树点有边权。然后有M个操作,分为三种:

操作1:把某个节点x的点权增加a。

操作2:把某个节点x为根的子树中所有点的点权都增加a。

操作3:询问某个节点x到根的路径中所有点的点权和。

【输入格式】

第一行两个整数N,M,表示点数和操作数。

接下来一行N个整数,表示树中节点的初始权值。

接下来N-1行每行两个正整数fr,to,表示该树中存在一条边(fr,to)。

再接下来M行,每行分别表示一次操作。其中第一个数表示该操作的种类(1~3),之后接这个操作的参数(x或者x a)。

【输出格式】

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

【样例输入】

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

【样例输出】

6

9

13

【提示】

对于30%的数据,N,M<=1000

对于50%的数据,N,M<=100000且数据随机。

对于100%的数据,N,M<=100000,且所有输入数据的绝对值都不会超过10^6。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<vector>
  8 #include<queue>
  9 using namespace std;
 10 typedef long long LL;
 11 const LL maxn=100010;
 12 inline LL read(){
 13     LL x=0,f=1;char ch=getchar();
 14     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 15     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 16     return x*f;
 17 }
 18 vector<LL> to[maxn];
 19 LL N,M;
 20 LL a[maxn];
 21 LL dep[maxn],fa[maxn],son[maxn],top[maxn],siz[maxn],id[maxn];
 22 LL val[maxn];
 23 LL num;
 24 inline void dfs1(LL rt,LL fath,LL deep){
 25     dep[rt]=deep; siz[rt]=1; fa[rt]=fath;
 26     for(LL i=0;i<to[rt].size();i++){
 27         LL y=to[rt][i];
 28         if(y!=fa[rt]){
 29             dfs1(y,rt,deep+1);
 30             siz[rt]+=siz[y];
 31             if(siz[son[rt]]<siz[y]) son[rt]=y;
 32         }
 33     }
 34 }
 35 inline void dfs2(LL rt,LL tp){
 36     top[rt]=tp; id[rt]=++num;
 37     if(son[rt]!=0) dfs2(son[rt],tp);
 38     for(LL i=0;i<to[rt].size();i++){
 39         LL y=to[rt][i];
 40         if(y!=fa[rt]&&y!=son[rt]){
 41             dfs2(y,y);
 42         }
 43     }
 44 }
 45 struct node{
 46     LL l,r;
 47     LL sum,lazy;
 48 }tree[maxn*8];
 49 inline void build(LL rt,LL l,LL r){
 50     tree[rt].l=l; tree[rt].r=r;
 51     if(l==r){
 52         tree[rt].sum=val[l];
 53         tree[rt].lazy=0;
 54         return ;
 55     }
 56     LL mid=(l+r)>>1;
 57     build(rt<<1,l,mid); build(rt<<1|1,mid+1,r);
 58     tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
 59 }
 60 inline void update_son(LL rt){
 61     LL d=tree[rt].lazy;
 62     if(d!=0){
 63         tree[rt<<1].sum+=(tree[rt<<1].r-tree[rt<<1].l+1)*d;
 64         tree[rt<<1|1].sum+=(tree[rt<<1|1].r-tree[rt<<1|1].l+1)*d;
 65         tree[rt<<1].lazy+=d; tree[rt<<1|1].lazy+=d;
 66         tree[rt].lazy=0;
 67     }
 68 }
 69 inline void change(LL rt,LL l,LL r,LL delta){
 70     if(l<=tree[rt].l&&tree[rt].r<=r){
 71         tree[rt].sum+=(tree[rt].r-tree[rt].l+1)*delta;
 72         tree[rt].lazy+=delta;
 73         return ;
 74     }
 75     update_son(rt);
 76     LL mid=(tree[rt].l+tree[rt].r)>>1;
 77     if(l<=mid) change(rt<<1,l,r,delta);
 78     if(mid+1<=r) change(rt<<1|1,l,r,delta);
 79     tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
 80 }
 81 inline LL query(LL rt,LL l,LL r){
 82     if(l<=tree[rt].l&&tree[rt].r<=r){
 83         return tree[rt].sum;
 84     }
 85     update_son(rt);
 86     LL ans=0;
 87     LL mid=(tree[rt].l+tree[rt].r)>>1;
 88     if(l<=mid) ans+=query(rt<<1,l,r);
 89     if(mid+1<=r) ans+=query(rt<<1|1,l,r);
 90      return ans;
 91 }
 92 inline void ASK(LL x){
 93     LL tp=top[x],ans=0;
 94     while(x!=0&&tp!=0){
 95         ans+=query(1,id[tp],id[x]);
 96         x=fa[tp]; tp=top[x];
 97     }
 98     printf("%lld
",ans);
 99 }
100 int main(){
101     N=read(); M=read();
102     for(LL i=1;i<=N;i++) a[i]=read();
103     for(LL i=1,u,v;i<=N-1;i++){
104         u=read(); v=read();
105         to[u].push_back(v); to[v].push_back(u);
106     }
107     dis[1]=a[1];
108     dfs1(1,0,1); dfs2(1,1);
109     for(LL i=1;i<=N;i++) val[id[i]]=a[i];
110     build(1,1,num);
111     for(LL i=1,kin;i<=M;i++){
112         kin=read();
113         if(kin==1){
114             LL x=read(),d=read();
115             change(1,id[x],id[x],d);
116         }
117         else if(kin==2){
118             LL x=read(),d=read();
119             change(1,id[x],id[x]+siz[x]-1,d);
120         }
121         else if(kin==3){
122             LL x=read();
123             ASK(x);
124         }
125     }
126     return 0;
127 }
原文地址:https://www.cnblogs.com/CXCXCXC/p/5022114.html