【BZOJ4712】洪水 树链剖分优化DP+线段树
【BZOJ4712】洪水
Description
Input
输入文件第一行包含一个数n,表示树的大小。
Output
对于每次询问操作,输出对应的答案,答案之间用换行隔开。
Sample Input
4 3 2 1
1 2
1 3
4 2
4
Q 1
Q 2
C 4 10
Q 1
Sample Output
1
4
题解:设每个点的DP值是f[x],每个点儿子的f之和为g[x],f[x]=min(g[x],v[x])。发现,由于v[x]只能变大,所以每次操作可能导致一些点从选g[x]变成选v[x],但只能导致一个点从选v[x]变成选g[x],所以对于从选v变成选g或从选g变成选v的,我们都可以暴力搞定(均摊的思想)。具体做法:
先改v[x],如果v[x]的增长导致了f[x]的改变,则令它父亲的g值+=改变值,然后递归它的父亲:
先让当前的g值+=该变量,如果f不变,则结束;如果原来选g,改完变成选v,那么记录该变量,继续修改它的父亲;如果原来选g,改完还是选g,那么一定是:当前点的连续几辈祖先都是原来选g改完也选g,那么我们二分找到深度最小的祖先,然后中间的g值都能用线段树直接修改。然后再继续修改这个祖先的父亲即可。
那么二分的过程具体如何实现呢?需要用线段树维护v[x]-g[x]的最小值,然后再树剖的时候,先判断当前链的链顶是否符合要求,如果不是,则在链内二分,否则在直接跳到下一条链上。
这样就保证了时间复杂度是$O(nlog_n^2)$的。
#include <cstdio>
#include <cstring>
#include <iostream>
#define lson x<<1
#define rson x<<1|1
using namespace std;
const int maxn=200010;
typedef long long ll;
int n,m,cnt;
int to[maxn<<1],next[maxn<<1],head[maxn],p[maxn],Q[maxn],dep[maxn],fa[maxn],top[maxn],siz[maxn],son[maxn];
char str[5];
ll sv[maxn<<2],ts[maxn<<2],sc[maxn<<2],v[maxn],g[maxn];
inline void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void dfs1(int x)
{
siz[x]=1;
for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa[x])
{
fa[to[i]]=x,dep[to[i]]=dep[x]+1,dfs1(to[i]),siz[x]+=siz[to[i]];
if(siz[to[i]]>siz[son[x]]) son[x]=to[i];
g[x]+=min(g[to[i]],v[to[i]]);
}
if(siz[x]==1) g[x]=1<<30;
}
void dfs2(int x,int tp)
{
p[x]=++p[0],Q[p[0]]=x,top[x]=tp;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa[x]&&to[i]!=son[x]) dfs2(to[i],to[i]);
}
inline void pushdown(int x)
{
if(ts[x]) sc[lson]-=ts[x],sc[rson]-=ts[x],ts[lson]+=ts[x],ts[rson]+=ts[x],ts[x]=0;
}
void build(int l,int r,int x)
{
if(l==r)
{
sv[x]=v[Q[l]],sc[x]=v[Q[l]]-g[Q[l]];
return ;
}
int mid=(l+r)>>1;
build(l,mid,lson),build(mid+1,r,rson);
sv[x]=min(sv[lson],sv[rson]),sc[x]=min(sc[lson],sc[rson]);
}
ll getg(int l,int r,int x,int a)
{
if(l==r) return sv[x]-sc[x];
pushdown(x);
int mid=(l+r)>>1;
if(a<=mid) return getg(l,mid,lson,a);
return getg(mid+1,r,rson,a);
}
ll getv(int l,int r,int x,int a,int b)
{
if(l==r) return sv[x];
pushdown(x);
int mid=(l+r)>>1;
if(b<=mid) return getv(l,mid,lson,a,b);
if(a>mid) return getv(mid+1,r,rson,a,b);
return min(getv(l,mid,lson,a,b),getv(mid+1,r,rson,a,b));
}
ll getc(int l,int r,int x,int a,int b)
{
if(a<=l&&r<=b) return sc[x];
pushdown(x);
int mid=(l+r)>>1;
if(b<=mid) return getc(l,mid,lson,a,b);
if(a>mid) return getc(mid+1,r,rson,a,b);
return min(getc(l,mid,lson,a,b),getc(mid+1,r,rson,a,b));
}
void upg(int l,int r,int x,int a,int b,ll c)
{
if(a<=l&&r<=b)
{
if(c==-1) sc[x]+=v[Q[l]]-sv[x],sv[x]=v[Q[l]];
else sc[x]-=c,ts[x]+=c;
return ;
}
pushdown(x);
int mid=(l+r)>>1;
if(a<=mid) upg(l,mid,lson,a,b,c);
if(b>mid) upg(mid+1,r,rson,a,b,c);
sv[x]=min(sv[lson],sv[rson]),sc[x]=min(sc[lson],sc[rson]);
}
inline void change(int x,ll d)
{
while(x)
{
ll gx=getg(1,n,1,p[x]),fx=min(gx,v[x]);
upg(1,n,1,p[x],p[x],d);
if(gx>=v[x]) return ;
if(gx+d>v[x]) d=v[x]-fx,x=fa[x];
else
{
if(top[x]==x) x=fa[x];
else if(getc(1,n,1,p[top[x]],p[x]-1)>=d)
{
upg(1,n,1,p[top[x]],p[x]-1,d);
x=fa[top[x]];
}
else
{
int l=p[top[x]],r=p[x],mid;
while(l<r)
{
mid=(l+r)>>1;
if(getc(1,n,1,mid,p[x]-1)>=d) r=mid;
else l=mid+1;
}
if(r<p[x]) upg(1,n,1,r,p[x]-1,d);
x=Q[r-1];
}
}
}
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
n=rd();
int i,a,b;
for(i=1;i<=n;i++) v[i]=rd();
memset(head,-1,sizeof(head));
for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
dep[1]=1,dfs1(1),dfs2(1,1);
m=rd();
build(1,n,1);
for(i=1;i<=m;i++)
{
scanf("%s",str);
if(str[0]=='C')
{
a=rd(),b=rd();
ll gx=getg(1,n,1,p[a]),fx=min(gx,v[a]);
v[a]+=b,upg(1,n,1,p[a],p[a],-1);
if(min(v[a],gx)>fx) change(fa[a],min(v[a],gx)-fx);
}
else a=rd(),printf("%lld\n",min(v[a],getg(1,n,1,p[a])));
}
return 0;
}//4 4 3 2 1 1 2 1 3 4 2 4 Q 1 Q 2 C 4 10 Q 1
【BZOJ4712】洪水 树链剖分优化DP+线段树的更多相关文章
- BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...
- BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- BZOJ 2243:染色(树链剖分+区间合并线段树)
[SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认 ...
- 【Codeforces】【网络流】【树链剖分】【线段树】ALT (CodeForces - 786E)
题意 现在有m个人,每一个人都特别喜欢狗.另外还有一棵n个节点的树. 现在每个人都想要从树上的某个节点走到另外一个节点,且满足要么这个人自带一条狗m,要么他经过的所有边h上都有一条狗. 2<=n ...
- LOJ2269 [SDOI2017] 切树游戏 【FWT】【动态DP】【树链剖分】【线段树】
题目分析: 好题.本来是一道好的非套路题,但是不凑巧的是当年有一位国家集训队员正好介绍了这个算法. 首先考虑静态的情况.这个的DP方程非常容易写出来. 接着可以注意到对于异或结果的计数可以看成一个FW ...
- Codeforces 856D - Masha and Cactus(树链剖分优化 dp)
题面传送门 题意: 给你一棵 \(n\) 个顶点的树和 \(m\) 条带权值的附加边 你要选择一些附加边加入原树中使其成为一个仙人掌(每个点最多属于 \(1\) 个简单环) 求你选择的附加边权值之和的 ...
- 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流
[BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ...
- HDU 5029 Relief grain 树链剖分打标记 线段树区间最大值
Relief grain Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...
- HYSBZ 4034 【树链剖分】+【线段树 】
<题目链接> 题目大意: 有一棵点数为 N 的树,以点 1 为根,且树点有权值.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x ...
随机推荐
- Python-PyQt4学习笔记
1.每个应用必须创建一个 QtGui.QApplication(sys.argv), 此时 QtGui.qApp 为此应用的实例 app = QtGui.QApplication(sys.argv) ...
- HTML-HTML5+CSS3权威指南阅读(三、CSS3)
不同的浏览器(包括-moz-代表的Mozilla Firefox, -ms-代表的Microsoft Internet Explorer等)厂商在发布正式版本之前之前, 试验各自对CSS3新特性的实现 ...
- golang使用sqlite
安装问题 在import sqlite的时候,golang build 出现以下错误, exec: "gcc": executable file not found in %PAT ...
- js操作时间 加法 减法 计算 格式化时间
Date.prototype.Format = function (fmt) { var o = { "M+": this.getMonth() + 1, //月份 "d ...
- ACM_数论_阶乘N!的末尾有几个零 和 末尾有多少个 1 nyoj 954
原文地址 首先阶乘的一个常识要知道就是25!的末尾6位全是0: 前言: <编程之美>这本书,爱不释手! 问题描述: 给定一个整数N,那么N的阶乘N!末尾有多少个0呢?例如:N=10,N!= ...
- H3C-WA2210升级
前几天升级了2210固件,做个记录 首先吐槽一点:华为官方给出的公共下载账号yx800根本没用..下不了官方提供的固件资料 组网准备: 升级之前要先看看原机版本(dis ver): 在升级版本之前,请 ...
- #include""和#include<>的区别
一般来说,就是搜索路径不同 #include ""先去搜用户当前路径(也就是调用编译器的路径),然后再去搜用户用-I选项指定的路径,最后再去搜索编译器默认指定的路径(也就是所谓的系 ...
- (译)Getting Started——1.3.3 Working with Foundation(使用Foundation框架)
在你使用Objective-C语言开发应用时,你会发现在开发中,你会用到很多框架.尤其是Foundation框架,该框架为应用提供了最基础的服务.Foundation框架包括了代表着基本数据类型的va ...
- 1.2 Activity
Activity是个应用组件,它给用户提供了为了完成某些工作而可以进行交互操作的界面,例如,电话详情,打电 话,发邮件,或是浏览地图.每一个Activity都有一个窗口来绘制自已的用户界面.通常来说, ...
- ECMall 中URL体系的改造思路
EC系列的产品都已停止更新很久了,但其对中国中小电商企业的影响无疑是巨大的.很多公司,都是直接拿来即改,改了即用. 但他们都有个问题,代码是比较传统的开发模式过来的,尤其ecshop.ECMall系统 ...