[BZOJ4712]洪水-[树链剖分+线段树]
Description
Solution
这道题真的是666。。
我们设g[x]为堵住该点所有子树的和,v[x]为堵住该点的代价,则f[x]=min(g[x],v[x])。现在我们要给v[x]加上to。
1,v[x]>=g[x],v[x]加多少都不会有影响,过;
2,v[x]<=g[x]&&v[x]+to<=g[x],则g[fa[x]]+=to,如果f[fa[x]]改变,则还需要接着往上推。
3,v[x]<=g[x]&&v[x]+to>g[x],则g[fa[x]]+=-v[x]+g[x],如果f[fa[x]]改变,同样需要接着往上推。
对于情况1,直接处理掉就ok了。
我们考虑优化情况2和3的处理。在这里我们采用树剖+线段树。线段树存储v[x]-g[x]。
对于点x,我们沿着重链往上,如果在某条重链上都是情况2或3,直接加就好;反之在这条重链上二分。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
int n,x,y;
ll v[],_g[],dp[],d;
struct node{int y,nxt;
}g[];int h[],tot=;
int m;char ch[]; int fa[],dep[],son[],top[],sz[];
int cnt=,dfn[],id[]; struct XD_TREE
{
ll mn[],tag[];
void build(int k,int l,int r)
{
if (l==r) {mn[k]=v[dfn[l]]-_g[dfn[l]];return;}
int mid=(l+r)/;
build(k<<,l,mid);build(k<<|,mid+,r);
mn[k]=min(mn[k<<],mn[k<<|]);
}
void downtag(int k)
{
mn[k<<]-=tag[k];mn[k<<|]-=tag[k];
tag[k<<]+=tag[k];tag[k<<|]+=tag[k];
tag[k]=;
}
int modify(int k,int l,int r,int askl,int askr,ll d)
{
if (l==r){
mn[k]-=d;tag[k]+=d;
if (mn[k]<=) return dfn[l];
return ;
}
if (askl<=l&&r<=askr){
if (mn[k]>d)
{
mn[k]-=d;tag[k]+=d;return ;
}
}
if (tag[k]!=) downtag(k);
int mid=(l+r)/,re=;
if (askr>mid) re=modify(k<<|,mid+,r,askl,askr,d);
if (askl<=mid&&!re) re=modify(k<<,l,mid,askl,askr,d);
mn[k]=min(mn[k<<],mn[k<<|]);
return re;
}
ll query(int k,int l,int r,int ask)
{
if (l==r) return mn[k];
if (tag[k]!=) downtag(k);
int mid=(l+r)/;
if (ask<=mid) return query(k<<,l,mid,ask);
else return query(k<<|,mid+,r,ask);
}
}X;
struct TREE_LINK//树剖
{
void dfs1(int x,int f)
{
fa[x]=f;dep[x]=dep[f]+;sz[x]=;
for(int i=h[x];i;i=g[i].nxt)
if (g[i].y!=f) {
dfs1(g[i].y,x);
sz[x]+=sz[g[i].y];
son[x]=(sz[son[x]]>=sz[g[i].y])?son[x]:g[i].y;
_g[x]+=dp[g[i].y];
}
if (sz[x]>) dp[x]=min(_g[x],v[x]);else dp[x]=v[x],_g[x]=1e9;
}
void dfs2(int x)
{
dfn[++cnt]=x;id[x]=cnt;
top[x]=son[fa[x]]==x?top[fa[x]]:x;
if (son[x]) dfs2(son[x]);
for (int i=h[x];i;i=g[i].nxt)
if (g[i].y!=fa[x]&&g[i].y!=son[x]) dfs2(g[i].y);
}
void work(int x,ll d)
{
if (!x||d<=) return;
while (x)
{
int t=X.modify(,,n,id[top[x]],id[x],d);
if (t) {work(fa[t],X.query(,,n,id[t])+d);break;}
x=fa[top[x]];
}
}
}T;
ll getg(int x){return v[x]-X.query(,,n,id[x]);}
int main()
{
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%lld",&v[i]);
for (int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
g[++tot]=node{y,h[x]};h[x]=tot;
g[++tot]=node{x,h[y]};h[y]=tot;
}
T.dfs1(,);
T.dfs2();
X.build(,,n);
scanf("%d",&m);
for (int i=;i<=m;i++)
{
scanf("%s",ch);
if (ch[]=='Q')
{
scanf("%d",&x);
ll gg=getg(x);
printf("%lld\n",min(gg,v[x]));
} else
{
scanf("%d%lld",&x,&d);
v[x]+=d;
X.modify(,,n,id[x],id[x],-d);
ll gg=getg(x);
if (v[x]-d>=gg) continue;
if (v[x]<=gg) T.work(fa[x],d);
else T.work(fa[x],gg-v[x]+d);
}
}
}
[BZOJ4712]洪水-[树链剖分+线段树]的更多相关文章
- 【bzoj4712】洪水 树链剖分+线段树维护树形动态dp
题目描述 给出一棵树,点有点权.多次增加某个点的点权,并在某一棵子树中询问:选出若干个节点,使得每个叶子节点到根节点的路径上至少有一个节点被选择,求选出的点的点权和的最小值. 输入 输入文件第一行包含 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
随机推荐
- Python数据类型-字典
字典(dict) 字典是key:value形式的一种表达形式,例如在Java中有map,JavaScript中的json,Redis中的hash等等这些形式.字典可以存储任意的对象,也可以是不同的数据 ...
- 打包工具的核心原理(转自:https://juejin.im/entry/5b223ebd518825748b569bda)
打包工具就是负责把一些分散的小模块,按照一定的规则整合成一个大模块的工具.与此同时,打包工具也会处理好模块之间的依赖关系,最终这个大模块将可以被运行在合适的平台中. 打包工具会从一个入口文件开始,分析 ...
- jquery 中 attr 和 prop 的区别
问题:在jQuery引入prop方法后,什么时候使用attr,什么时候使用prop,两者区别. 判断: 对于HTML元素本身所有的固有属性,在处理的时候,使用prop方法 对于HTML元素后来我们自己 ...
- 俄罗斯方块 UWP 版
UWP跟 WPF编程模型一致,不过UWP做了精简,而且不同的系统的API还略有不同.不同的地方有以下几点: 1.动画.动画除了故事版,还有其它的实现方式. 2.异步方法.UWP中的方法调用,大部分都是 ...
- Java上机试题1
1. 有一串字符串String s = "ababab", 这个字符串可以看做由3个"ab"构成,即n=3, L = "ab", s = n ...
- iOS 使约束带动画效果(Animate NSLayoutconstraints)
http://stackoverflow.com/questions/12926566/are-nslayoutconstraints-animatable http://stackoverflow. ...
- Servlet基础知识总结
Servlet是JavaWeb应用开发的核心组件.Servlet运行在Servlet容器中(例如最常用的Tomcat),它可以为各种客户请求提供相应服务.Servlet可以轻松完成以下任务: 动态生成 ...
- JS常见算法题目
最近收集了几个经典JS题目,比较有代表性,分享一下: 1.xiaoshuo-ss-sfff-fe 变为驼峰xiaoshuoSsSfffFe function getCamelCase(str ...
- 每天一个linux命令(1):find命令之exec
ind是我们很常用的一个Linux命令,但是我们一般查找出来的并不仅仅是看看而已,还会有进一步的操作,这个时候exec的作用就显现出来了. exec解释:-exec 参数后面跟的是command命令, ...
- kafka搭建到配置borker集群(项目开发-区块链)
(以下分享了搭建kafka需要使用到的命令,差不多齐了,这里没有提到kafka-manager ,同学可以在网上自行查找) 最近公司的项目比较紧,先说下使用kafka的用处: 要替代原来 撮合引擎发数 ...