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 }

 

posted @ 2019-01-01 20:05  Unstoppable728  阅读(197)  评论(0编辑  收藏  举报