1. 程式人生 > >BZOJ4712: 洪水(樹鏈剖分維護Dp)

BZOJ4712: 洪水(樹鏈剖分維護Dp)

Description

小A走到一個山腳下,準備給自己造一個小屋。這時候,小A的朋友(op,又叫管理員)打開了創造模式,然後飛到 山頂放了格水。於是小A面前出現了一個瀑布。作為平民的小A只好老實巴交地爬山堵水。那麼問題來了:我們把這 個瀑布看成是一個n個節點的樹,每個節點有權值(爬上去的代價)。小A要選擇一些節點,以其權值和作為代價將 這些點刪除(堵上),使得根節點與所有葉子結點不連通。問最小代價。不過到這還沒結束。小A的朋友覺得這樣 子太便宜小A了,於是他還會不斷地修改地形,使得某個節點的權值發生變化。不過到這還沒結束。小A覺得朋友做 得太絕了,於是放棄了分離所有葉子節點的方案。取而代之的是,每次他只要在某個子樹中(和子樹之外的點完全 無關)。於是他找到你。

Input

 輸入檔案第一行包含一個數n,表示樹的大小。

接下來一行包含n個數,表示第i個點的權值。 接下來n-1行每行包含兩個數fr,to。表示書中有一條邊(fr,to)。 接下來一行一個整數,表示操作的個數。 接下來m行每行表示一個操作,若該行第一個數為Q,則表示詢問操作,後面跟一個引數x,表示對應子樹的根;若 為C,則表示修改操作,後面接兩個引數x,to,表示將點x的權值加上to。 n<=200000,保證任意to都為非負數

Output

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

Sample Input

4
4 3 2 1
1 2
1 3
4 2
4
Q 1
Q 2
C 4 10
Q 1

Sample Output

3
1
4

解題思路:

程式碼:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll spc<<1
  5 #define rrr spc<<1|1
  6 typedef long long lnt;
  7 const int N=200010
; 8 struct trnt{ 9 lnt minv; 10 lnt lzt; 11 }tr[N<<2]; 12 struct pnt{ 13 int hd; 14 int fa; 15 int tp; 16 int dp; 17 int wgt; 18 int mxs; 19 int ind; 20 lnt val; 21 lnt f; 22 lnt sigf; 23 }p[N]; 24 struct ent{ 25 int twd; 26 int lst; 27 }e[N<<1]; 28 int cnt; 29 int n,m; 30 int dfn; 31 int plc[N]; 32 char cmd[100]; 33 void ade(int f,int t) 34 { 35 cnt++; 36 e[cnt].twd=t; 37 e[cnt].lst=p[f].hd; 38 p[f].hd=cnt; 39 return ; 40 } 41 void Basic_dfs(int x,int f) 42 { 43 p[x].fa=f; 44 p[x].dp=p[f].dp+1; 45 p[x].wgt=1; 46 int maxs=-1; 47 for(int i=p[x].hd;i;i=e[i].lst) 48 { 49 int to=e[i].twd; 50 if(to==f) 51 continue; 52 Basic_dfs(to,x); 53 p[x].sigf+=p[to].f; 54 p[x].wgt+=p[to].wgt; 55 if(maxs<p[to].wgt) 56 { 57 maxs=p[to].wgt; 58 p[x].mxs=to; 59 } 60 } 61 if(!p[x].mxs) 62 p[x].sigf=0x3f3f3f3f; 63 p[x].f=std::min(p[x].val,p[x].sigf); 64 return ; 65 } 66 void Build_dfs(int x,int top) 67 { 68 if(!x) 69 return ; 70 p[x].tp=top; 71 p[x].ind=++dfn; 72 plc[dfn]=x; 73 Build_dfs(p[x].mxs,top); 74 for(int i=p[x].hd;i;i=e[i].lst) 75 { 76 int to=e[i].twd; 77 if(p[to].ind) 78 continue; 79 Build_dfs(to,to); 80 } 81 return ; 82 } 83 void pushup(int spc) 84 { 85 tr[spc].minv=std::min(tr[lll].minv,tr[rrr].minv); 86 return ; 87 } 88 void add(int spc,lnt v) 89 { 90 tr[spc].lzt+=v; 91 tr[spc].minv-=v; 92 return ; 93 } 94 void pushdown(int spc) 95 { 96 if(tr[spc].lzt) 97 { 98 add(lll,tr[spc].lzt); 99 add(rrr,tr[spc].lzt); 100 tr[spc].lzt=0; 101 } 102 return ; 103 } 104 void build(int l,int r,int spc) 105 { 106 if(l==r) 107 { 108 tr[spc].minv=p[plc[l]].val-p[plc[l]].sigf; 109 return ; 110 } 111 int mid=(l+r)>>1; 112 build(l,mid,lll); 113 build(mid+1,r,rrr); 114 pushup(spc); 115 return ; 116 } 117 void update(int l,int r,int pos,int spc,lnt v) 118 { 119 if(l==r) 120 { 121 add(spc,-v); 122 return ; 123 } 124 int mid=(l+r)>>1; 125 pushdown(spc); 126 if(pos<=mid) 127 update(l,mid,pos,lll,v); 128 else 129 update(mid+1,r,pos,rrr,v); 130 pushup(spc); 131 return ; 132 } 133 int scupdate(int l,int r,int ll,int rr,int spc,lnt v) 134 { 135 if(l>rr||ll>r) 136 return 0; 137 if(l==r) 138 { 139 add(spc,v); 140 if(tr[spc].minv<=0) 141 return plc[l]; 142 return 0; 143 } 144 if(ll<=l&&r<=rr&&tr[spc].minv>v) 145 { 146 add(spc,v); 147 return 0; 148 } 149 int mid=(l+r)>>1; 150 pushdown(spc); 151 int plcc=scupdate(mid+1,r,ll,rr,rrr,v); 152 if(!plcc) 153 plcc=scupdate(l,mid,ll,rr,lll,v); 154 pushup(spc); 155 return plcc; 156 } 157 lnt query(int l,int r,int pos,int spc) 158 { 159 if(l==r) 160 return tr[spc].minv; 161 int mid=(l+r)>>1; 162 pushdown(spc); 163 if(pos<=mid) 164 return query(l,mid,pos,lll); 165 return query(mid+1,r,pos,rrr); 166 } 167 void Update(int x,lnt v) 168 { 169 if(v<=0||!x) 170 return ; 171 while(x) 172 { 173 int tp=scupdate(1,n,p[p[x].tp].ind,p[x].ind,1,v); 174 if(!tp) 175 x=p[p[x].tp].fa; 176 else{ 177 Update(p[tp].fa,query(1,n,p[tp].ind,1)+v); 178 return ; 179 } 180 } 181 } 182 int main() 183 { 184 scanf("%d",&n); 185 for(int i=1;i<=n;i++) 186 scanf("%d",&p[i].val); 187 for(int i=1;i<n;i++) 188 { 189 int a,b; 190 scanf("%d%d",&a,&b); 191 ade(a,b); 192 ade(b,a); 193 } 194 Basic_dfs(1,1); 195 Build_dfs(1,1); 196 build(1,n,1); 197 scanf("%d",&m); 198 while(m--) 199 { 200 scanf("%s",cmd+1); 201 if(cmd[1]=='Q') 202 { 203 int x; 204 scanf("%d",&x); 205 printf("%lld\n",std::min(p[x].val,p[x].val-query(1,n,p[x].ind,1))); 206 }else{ 207 int x,v; 208 scanf("%d%d",&x,&v); 209 if(!v) 210 continue; 211 p[x].val+=v; 212 update(1,n,p[x].ind,1,v); 213 lnt tmp=p[x].val-query(1,n,p[x].ind,1); 214 p[x].f=std::min(p[x].val,tmp); 215 Update(p[x].fa,p[x].f+v-p[x].val); 216 } 217 } 218 return 0; 219 }