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,m<=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

Sol

不会ddp,所以我就用树剖+二分写了。。。

首先我们发现\(f[x]=min(v[x],g[x])\),\(g[x]\)表示x儿子的f总和。

每次修改vi,会导致这个点往父亲的链中的某些g和f发生改变。

具体地,我们先修改某个点的g,然后如果fa[x]加上f[x]的delta之后会变成选v[fa[x]],那么我们直接记录新的delta值然后继续修改fa[x]的父亲,如果还是选g,那么后面的累加会越来越大,会在一个地方出现选v的分界点,我们通过跳整条链以及如果分界点就在链中就二分的做法修改这个仍然选g的区间,显然这个不会改变delta值,所以直接调用线段树函数即可。接着继续往上修改。

线段树维护v[i],g[i],v[i]-g[i]的其中两种即可。线段树维护的是区间min值,然后upd函数支持区间修改和单点更新(如果修改了某个v就要在线段树中更新)。

Code

最近几个月中写过的最长的一个数据结构题:

正好100行。。。。。。。

#include <bits/stdc++.h>
#define ls x<<1
#define rs x<<1|1
#define ll long long
using namespace std;
int n,m,x,y,siz[200005],fa[200005],dep[200005],top[200005],id[200005],rel[200005],son[200005];
ll sv[800005],sc[800005],tg[800005],v[800005],g[800005],fx;vector<int>e[200005];char op[5];
int dfs1(int x)
{
for(int i=0;i<e[x].size();i++) if(e[x][i]!=fa[x])
{
fa[e[x][i]]=x;dep[e[x][i]]=dep[x]+1;siz[x]+=dfs1(e[x][i]);
if(siz[e[x][i]]>siz[son[x]]) son[x]=e[x][i];g[x]+=min(g[e[x][i]],v[e[x][i]]);
}
if(!siz[x]) g[x]=1<<30;
return ++siz[x];
}
void dfs2(int x,int Fa)
{
top[x]=Fa;id[x]=++id[0];rel[id[x]]=x;
if(son[x]) dfs2(son[x],Fa);
for(int i=0;i<e[x].size();i++) if(e[x][i]!=fa[x]&&e[x][i]!=son[x]) dfs2(e[x][i],e[x][i]);
}
void down(int x){if(!tg[x]) return;sc[ls]-=tg[x];sc[rs]-=tg[x];tg[ls]+=tg[x];tg[rs]+=tg[x];tg[x]=0;}
void build(int x,int l,int r)
{
if(l==r){sv[x]=v[rel[l]];sc[x]=v[rel[l]]-g[rel[l]];return;}
int mid=(l+r)>>1;build(ls,l,mid);build(rs,mid+1,r);
sv[x]=min(sv[ls],sv[rs]);sc[x]=min(sc[ls],sc[rs]);
}
ll getg(int x,int l,int r,int b,int e)
{
if(b<=l&&r<=e) return sv[x]-sc[x];
down(x);int mid=(l+r)>>1;
if(e<=mid) return getg(ls,l,mid,b,e);
if(b>mid) return getg(rs,mid+1,r,b,e);
return min(getg(ls,l,mid,b,e),getg(rs,mid+1,r,b,e));
}
ll getv(int x,int l,int r,int b,int e)
{
if(b<=l&&r<=e) return sv[x];
down(x);int mid=(l+r)>>1;
if(e<=mid) return getv(ls,l,mid,b,e);
if(b>mid) return getv(rs,mid+1,r,b,e);
return min(getv(ls,l,mid,b,e),getv(rs,mid+1,r,b,e));
}
ll getc(int x,int l,int r,int b,int e)
{
if(b<=l&&r<=e) return sc[x];
down(x);int mid=(l+r)>>1;
if(e<=mid) return getc(ls,l,mid,b,e);
if(b>mid) return getc(rs,mid+1,r,b,e);
return min(getc(ls,l,mid,b,e),getc(rs,mid+1,r,b,e));
}
void upd(int x,int l,int r,int b,int e,ll o)
{
if(b<=l&&r<=e){if(o==-1) sc[x]+=v[rel[l]]-sv[x],sv[x]=v[rel[l]];else sc[x]-=o,tg[x]+=o;return;}
down(x);int mid=(l+r)>>1;
if(b<=mid) upd(ls,l,mid,b,e,o);if(e>mid) upd(rs,mid+1,r,b,e,o);
sv[x]=min(sv[ls],sv[rs]);sc[x]=min(sc[ls],sc[rs]);
}
void modify(int x,ll d)
{
while(x)
{
ll gx=getg(1,1,n,id[x],id[x]),fx=min(gx,v[x]);
upd(1,1,n,id[x],id[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,1,n,id[top[x]],id[x]-1)>=d) upd(1,1,n,id[top[x]],id[x]-1,d),x=fa[top[x]];
else
{
int l=id[top[x]],r=id[x];
for(int mid=(l+r)>>1;l<r;mid=(l+r)>>1) if(getc(1,1,n,mid,id[x]-1)>=d) r=mid;else l=mid+1;
if(r<id[x]) upd(1,1,n,r,id[x]-1,d);x=rel[r-1];
}
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&v[i]);
for(int i=1;i<n;i++) scanf("%d%d",&x,&y),e[x].push_back(y),e[y].push_back(x);
dfs1(1);dfs2(1,1);build(1,1,n);
for(scanf("%d",&m);m--;)
{
scanf("%s",op);
if(op[0]=='C')
{
scanf("%d%d",&x,&y);ll gx=getg(1,1,n,id[x],id[x]),fx=min(gx,v[x]);
v[x]+=y;upd(1,1,n,id[x],id[x],-1);
if(min(gx,v[x])>fx) modify(fa[x],min(gx,v[x])-fx);
}
else scanf("%d",&x),printf("%lld\n",min(v[x],getg(1,1,n,id[x],id[x])));
}
}

[bzoj4712]洪水 线段树+树链剖分维护动态dp+二分的更多相关文章

  1. 4712: 洪水 基于链分治的动态DP

    国际惯例的题面:看起来很神的样子......如果我说这是动态DP的板子题你敢信?基于链分治的动态DP?说人话,就是树链剖分线段树维护DP.既然是DP,那就先得有转移方程.我们令f[i]表示让i子树中的 ...

  2. 线段树&数链剖分

    傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...

  3. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5020  Solved: 1872[Submit][Status ...

  4. [树链剖分]BZOJ3589动态树

    题目描述 别忘了这是一棵动态树, 每时每刻都是动态的. 小明要求你在这棵树上维护两种事件 事件0: 这棵树长出了一些果子, 即某个子树中的每个节点都会长出K个果子. 事件1: 小明希望你求出几条树枝上 ...

  5. CF Contest 526 G. Spiders Evil Plan 长链剖分维护贪心

    LINK:Spiders Evil Plan 非常巧妙的题目. 选出k条边使得这k条边的路径覆盖x且覆盖的边的边权和最大. 类似于桥那道题还是选择2k个点 覆盖x那么以x为根做长链剖分即可. 不过这样 ...

  6. 长链剖分优化树形DP总结

    长链剖分 规定若\(x\)为叶结点,则\(len[x]=1\). 否则定义\(preferredchild[x]\)(以下简称\(pc[x]\),称\(pc[x]\)为\(x\)的长儿子)为\(x\) ...

  7. BZOJ4712: 洪水(树链剖分维护Dp)

    Description 小A走到一个山脚下,准备给自己造一个小屋.这时候,小A的朋友(op,又叫管理员)打开了创造模式,然后飞到 山顶放了格水.于是小A面前出现了一个瀑布.作为平民的小A只好老实巴交地 ...

  8. bzoj 3672: [Noi2014]购票 树链剖分+维护凸包

    3672: [Noi2014]购票 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 480  Solved: 212[Submit][Status][D ...

  9. BZOJ4543 POI2014 Hotel加强版 【长链剖分】【DP】*

    BZOJ4543 POI2014 Hotel加强版 Description 同OJ3522 数据范围:n<=100000 Sample Input 7 1 2 5 7 2 5 2 3 5 6 4 ...

随机推荐

  1. 迷你MVVM框架 avalonjs 学习教程8、属性操作

    属性操作是DOM操作很大的一块,它包括类名操作,表单元素的value属性操作,元素固有属性的管理,元素自定义属性的管理,某些元素的一些布尔属性的操作.大多数情况下,元素属性的值是字符串类型,我们称之为 ...

  2. 设置 UILabel 和 UITextField 的 Padding 或 Insets (理解UIEdgeInsets)

    转自http://unmi.cc/uilable-uitextfield-padding-insets 主要是理解下UIEdgeInsets在IOS UI里的意义. 靠,这货其实就是间隔,起个名字这么 ...

  3. Python运维开发基础06-语法基础

    上节作业回顾 (讲解+温习120分钟) #!/usr/bin/env python3 # -*- coding:utf-8 -*- # author:Mr.chen # 添加商家入口和用户入口并实现物 ...

  4. Fundamentals of Garbage Collection

    [Fundamentals of Garbage Collection] 1.Reclaims objects that are no longer being used, clears their ...

  5. Unity3D 游戏在 iOS 上因为 trampolines 闪退的原因与解决办法

    崩溃的情况 进入游戏一会儿,神马都不要做,双手离开手机,盯着屏幕看吧,游戏会定时从服务器那儿读取一些数据,时间一长,闪退了.尼玛问题是神马呢?完全没有头绪,不过大体猜测是因为网络请求导致的,那么好,先 ...

  6. Solidity根据精度来表示浮点数

    https://stackoverflow.com/questions/42738640/division-in-ethereum-solidity/42739843 pragma solidity ...

  7. WPF设置Window的数据上下文(DataContext)为自身

    WPF设置Window的数据上下文(DataContext)为自身的XAML: DataContext="{Binding RelativeSource={RelativeSource Se ...

  8. 友盟统计小白教程:创建应用,申请appkey

    上回书讲到,我们已经和一个靠谱的人选择一个靠谱的统计平台注册了一个帐号,下面就该创建一个应用了. 介绍一个基础知识: appkey:友盟识别app的唯一标识,目前友盟平台上超过500000款App,每 ...

  9. word 写博客,直接上传

    目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...

  10. 2016-2017-2 20155223 实验二 《Java面向对象程序设计》

    2016-2017-2 苏黄永郦 实验二 实验报告 前期准备工作--程序安装 -问题一 开始的时候我就在老师博客的指导下安装IDEA插件JUnit Generator V2.0.当然我的IDEA肯定没 ...