1. 程式人生 > >洛谷——P3178 [HAOI2015]樹上操作

洛谷——P3178 [HAOI2015]樹上操作

turn const blank .org define con ret ont wap

https://www.luogu.org/problem/show?pid=3178#sub

題目描述

有一棵點數為 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 ) 。

輸出格式:

對於每個詢問操作,輸出該詢問的答案。答案之間用換行隔開。

輸入輸出樣例

輸入樣例#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 。

樹剖模板練習

  1 #include <algorithm>
  2 #include <cstdio>
  3 
  4 #define
LL long long 5 6 using namespace std; 7 8 const LL N(100000+15); 9 const LL M(100000+15); 10 LL n,m,u,v,w,op,val[N]; 11 12 LL head[N],sumedge; 13 struct Edge 14 { 15 LL u,v,next; 16 Edge(LL u=0,LL v=0,LL next=0): 17 u(u),v(v),next(next){} 18 }edge[M<<1];
19 inline void ins(LL u,LL v) 20 { 21 edge[++sumedge]=Edge(u,v,head[u]); 22 head[u]=sumedge; 23 } 24 25 LL size[N],deep[N],dad[N],son[N],top[N],dfn[N],id[N],cnt; 26 void DFS(LL x,LL father,LL deepth) 27 { 28 deep[x]=deepth; 29 dad[x]=father; 30 size[x]=1; 31 for(LL i=head[x];i;i=edge[i].next) 32 { 33 LL v=edge[i].v; 34 if(dad[x]==v) continue; 35 DFS(v,x,deepth+1); 36 size[x]+=size[v]; 37 if(size[son[x]]<size[v]) son[x]=v; 38 } 39 } 40 void DFS_(LL x,LL Top) 41 { 42 top[x]=Top; 43 id[x]=++cnt,dfn[cnt]=x; 44 if(son[x]) DFS_(son[x],Top); 45 for(LL i=head[x];i;i=edge[i].next) 46 { 47 LL v=edge[i].v; 48 if(dad[x]!=v&&son[x]!=v) DFS_(v,v); 49 } 50 } 51 52 struct Tree 53 { 54 LL l,r,mid,flag,val; 55 }tree[N<<2]; 56 inline void Tree_up(LL now) 57 { 58 tree[now].val=tree[now<<1].val+tree[now<<1|1].val; 59 } 60 void Tree_down(LL now) 61 { 62 tree[now<<1].flag+=tree[now].flag; 63 tree[now<<1].val+=(tree[now].mid-tree[now].l+1)*tree[now].flag; 64 tree[now<<1|1].flag+=tree[now].flag; 65 tree[now<<1|1].val+=(tree[now].r-tree[now].mid)*tree[now].flag; 66 tree[now].flag=0; 67 } 68 void Tree_build(LL now,LL l,LL r) 69 { 70 tree[now].l=l;tree[now].r=r; 71 if(l==r) 72 { 73 tree[now].val=val[dfn[l]]; 74 return ; 75 } 76 tree[now].mid=l+r>>1; 77 Tree_build(now<<1,l,tree[now].mid); 78 Tree_build(now<<1|1,tree[now].mid+1,r); 79 Tree_up(now); 80 } 81 void Tree_change(LL now,LL l,LL r,LL x) 82 { 83 84 if(tree[now].l==l&&tree[now].r==r) 85 { 86 tree[now].flag+=x; 87 tree[now].val+=(r-l+1)*x; 88 return ; 89 } 90 if(tree[now].flag) Tree_down(now); 91 if(tree[now].mid>=r) Tree_change(now<<1,l,r,x); 92 else if(tree[now].mid<l) Tree_change(now<<1|1,l,r,x); 93 else 94 { 95 Tree_change(now<<1,l,tree[now].mid,x); 96 Tree_change(now<<1|1,tree[now].mid+1,r,x); 97 } 98 Tree_up(now); 99 } 100 LL Tree_query(LL now,int l,int r) 101 { 102 if(tree[now].l==l&&tree[now].r==r) 103 return tree[now].val; 104 if(tree[now].flag) Tree_down(now); 105 if(tree[now].mid>=r) return Tree_query(now<<1,l,r); 106 else if(tree[now].mid<l) return Tree_query(now<<1|1,l,r); 107 else return Tree_query(now<<1,l,tree[now].mid)+Tree_query(now<<1|1,tree[now].mid+1,r); 108 } 109 110 LL List_query(LL x,LL y) 111 { 112 LL ret=0; 113 for(;top[x]!=top[y];x=dad[top[x]]) 114 { 115 if(deep[top[x]]<deep[top[y]]) swap(x,y); 116 ret+=Tree_query(1,id[top[x]],id[x]); 117 } 118 if(deep[x]<deep[y]) swap(x,y); 119 ret+=Tree_query(1,id[y],id[x]); 120 return ret; 121 } 122 123 int if_,ch; 124 inline void read (LL &x) 125 { 126 if_=x=0;ch=getchar(); 127 for(;ch<0||ch>9;ch=getchar()) 128 if(ch==-) if_=1; 129 for(;ch>=0&&ch<=9;ch=getchar()) 130 x=x*10+ch-0; 131 if(if_) x=(~x)+1; 132 } 133 134 int main() 135 { 136 read(n); read(m); 137 for(LL i=1;i<=n;i++) 138 read(val[i]); 139 for(LL i=1;i<n;i++) 140 { 141 read(u); read(v); 142 ins(u,v),ins(v,u); 143 } 144 DFS(1,0,1);DFS_(1,1); 145 Tree_build(1,1,n); 146 for(;m--;) 147 { 148 read(op); 149 if(op==1) 150 { 151 read(u); read(w); 152 Tree_change(1,id[u],id[u],w); 153 } 154 else if(op==2) 155 { 156 read(u); read(w); 157 Tree_change(1,id[u],id[u]+size[u]-1,w); 158 } 159 else 160 { 161 read(u); 162 printf("%lld\n",List_query(u,1)); 163 } 164 } 165 return 0; 166 }

洛谷——P3178 [HAOI2015]樹上操作