【洛谷P4719】动态dp 动态dp模板
题目大意:给你一颗$n$个点的树,点有点权,有$m$次操作,每次操作给定$x$,$y$,表示修改点$x$的权值为$y$。
你需要在每次操作之后求出这棵树的最大权独立集的权值大小。
数据范围:$n,m≤1e5$
我们显然可以得出一个$O(nm)$的暴力做法,每次修改完后$dp$一次,然而这个显然会超时。
考虑当树退化成链时的简单做法。
我们用线段树维护每个区间的答案。对于区间$[l,r]$,我们维护一个$2×2$的答案矩阵$ans$。
设$ans[0][0]$表示区间左端点可能被选择,右端点一定不被选择时的最大值。
设$ans[0][1]$表示区间左端点可能被选择,右端点可能被选择时的最大值。
设$ans[1][0]$表示区间左端点一定不被选择,右端点一定不被选择时的最大值。
设$ans[1][1]$表示区间左端点一定不被选择,右端点可能被选择时的最大值。
对于叶节点,显然$ans[0][0]=ans[0][1]=0$,$ans[1][0]=val[x]$,$ans[1][1]=-INF$。
考虑已经求出$[l,mid]$,$[mid+1,r]$两个区间的答案,如何合并出$[l,r]$的答案。
不难发现$ans[0][0]=max(ansl[0][0]+ansr[0][0],ansl[0][1]+ansr[1][0])$;
$ans[0][1],ans[1][0],ans[1][1]$的转移都长得差不多。
每次修改一个权值,我们可以通过$pushup$更新区间的答案矩阵。
考虑把这个做法扩展到树上,我们通过树链剖分将整棵树剖成若干条链,对于每一条链我们就用如上所述的方式进行维护。对于接有轻儿子的链上节点,我们将轻儿子产生的共吸纳累计,将其加到链上节点上即可。
(细节可以看代码)
时间复杂度:$O(m log^2n)$。
#include<bits/stdc++.h>
#define ls (x<<1)
#define rs (x<<1|1)
#define mid ((a[x].l+a[x].r)>>1)
#define L long long
#define INF 1000000007
#define M 100005
using namespace std; struct edge{int u,next;}e[M*]={}; int head[M]={},use=;
void add(int x,int y){use++;e[use].u=y;e[use].next=head[x];head[x]=use;}
int val[M]={},n,m,f[M][]={}; int siz[M]={},son[M]={},dn[M]={},top[M]={},dfn[M]={},rec[M]={},fa[M]={},t=; void dfs1(int x){
siz[x]=;
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa[x]){
fa[e[i].u]=x;
dfs1(e[i].u);
siz[x]+=siz[e[i].u];
if(siz[son[x]]<siz[e[i].u]) son[x]=e[i].u;
}
}
void dfs2(int x,int Top){
top[x]=Top; dfn[x]=++t; rec[t]=x;
if(son[x]) dfs2(son[x],Top),dn[x]=dn[son[x]];
else dn[x]=x;
for(int i=head[x];i;i=e[i].next)
if(e[i].u!=fa[x]&&e[i].u!=son[x])
dfs2(e[i].u,e[i].u);
}
void dp(int x,int fa){
f[x][]=val[x];
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa){
dp(e[i].u,x);
f[x][]+=max(f[e[i].u][],f[e[i].u][]);
f[x][]+=f[e[i].u][];
}
} struct mat{
int a[][]; mat(){memset(a,,sizeof(a));}
mat(int x){a[][]=a[][]=a[][]=a[][]=x;}
mat(int a1,int a2,int a3,int a4){a[][]=a1; a[][]=a2; a[][]=a3; a[][]=a4;}
friend mat operator *(mat a,mat b){
mat c=-INF;
for(int i=;i<;i++)
for(int j=;j<;j++)
for(int k=;k<;k++)
c.a[i][j]=max(c.a[i][j],a.a[i][k]+b.a[k][j]);
return c;
}
}wei[M];
struct seg{int l,r;mat a;}a[M<<];
void pushup(int x){a[x].a=a[ls].a*a[rs].a;} void build(int x,int l,int r){
a[x].l=l; a[x].r=r;
if(l==r){
int u=rec[l],g0=,g1=val[u];
for(int i=head[u];i;i=e[i].next)
if(e[i].u!=son[u]&&e[i].u!=fa[u]){
g0+=max(f[e[i].u][],f[e[i].u][]);
g1+=f[e[i].u][];
}
a[x].a=wei[l]=mat(g0,g0,g1,-INF);
return;
}
build(ls,l,mid);
build(rs,mid+,r);
pushup(x);
}
void updata(int x,int k){
if(a[x].l==a[x].r) return void(a[x].a=wei[k]);
if(k<=mid) updata(ls,k);
else updata(rs,k);
pushup(x);
} mat query(int x,int l,int r){
if(l<=a[x].l&&a[x].r<=r) return a[x].a;
mat res;
if(l<=mid) res=query(ls,l,r);
if(mid<r){
if(l<=mid) return res*query(rs,l,r);
return query(rs,l,r);
}else return res;
}
mat query(int x){return query(,dfn[top[x]],dfn[dn[x]]);}
void solve(){mat hh=query(); printf("%d\n",max(hh.a[][],hh.a[][]));} void Updata(int x,int Val){
wei[dfn[x]].a[][]+=Val-val[x]; val[x]=Val;
while(x){ mat last=query(x);
int lg0=max(last.a[][],last.a[][]),lg1=last.a[][]; updata(,dfn[x]); mat now=query(x);
int ng0=max(now.a[][],now.a[][]),ng1=now.a[][]; x=fa[top[x]]; if(!x) return; int g0=ng0-lg0,g1=ng1-lg1;
wei[dfn[x]].a[][]+=g0;
wei[dfn[x]].a[][]+=g0;
wei[dfn[x]].a[][]+=g1;
}
} int main(){
//freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",val+i);
for(int i=,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs1();
dfs2(,);
dp(,);
build(,,n);
//solve();
while(m--){
int x,y; scanf("%d%d",&x,&y);
Updata(x,y);
solve();
}
}
【洛谷P4719】动态dp 动态dp模板的更多相关文章
- 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)
洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\).我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...
- 洛谷P4719 【模板】"动态 DP"&动态树分治
[模板]"动态 DP"&动态树分治 第一道动态\(DP\)的题,只会用树剖来做,全局平衡二叉树什么的就以后再学吧 所谓动态\(DP\),就是在原本的\(DP\)求解的问题上 ...
- 洛谷p1052过河 路径压缩+dp
洛谷 P1052 过河 思路部分可以看这篇博客 我将在这里对其进行一些解释与补充 首先我们先看题 乍一看 这不是模板题吗 然后开开心心的敲了一个简单dp上去 #include<iostream& ...
- 洛谷2344 奶牛抗议(DP+BIT+离散化)
洛谷2344 奶牛抗议 本题地址:http://www.luogu.org/problem/show?pid=2344 题目背景 Generic Cow Protests, 2011 Feb 题目描述 ...
- Lightning Conductor 洛谷P3515 决策单调性优化DP
遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森. 先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬. 废话不多说,看题: 题目大意 已知一个长度为n的序 ...
- 洛谷P1541 乌龟棋(四维DP)
To 洛谷.1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游 ...
- 【洛谷】P1052 过河【DP+路径压缩】
P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙 ...
- 【题解】洛谷P1052 [NOIP2005TG] 过河(DP+离散化)
题目来源:洛谷P1052 思路 一开始觉得是贪心 但是仔细一想不对 是DP 再仔细一看数据不对 有点大 如果直接存下的话 显然会炸 那么就需要考虑离散化 因为一步最大跳10格 那么我们考虑从1到10都 ...
- 洛谷1736(二维dp+预处理)
洛谷1387的进阶版,但很像. 1387要求是“全为1的正方形”,取dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1]))吧?这个有“只有对 ...
- bzoj3295 洛谷P3157、1393 动态逆序对——树套树
题目:bzoj3295 https://www.lydsy.com/JudgeOnline/problem.php?id=3295 洛谷 P3157(同一道题) https://www.luogu.o ...
随机推荐
- DB2 字符串的字段转为整形时的问题
正确语句: select int(cast(substr(dpt_leader_ids,4,posstr(dpt_leader_ids,',0)')-4) as varchar(8))), d.* f ...
- 让IIS 7 如同IIS 8 第一次请求不变慢
当我们把网站部署在IIS7或IIS6S的时候,每当IIS或是Application Pool重启后,第一次请求网站反应总是很慢,原因大家都知道(不知道可以参考这个动画说明ASP.NET网页第一个Req ...
- 马婕 2014年MBA,mpacc备考 报刊宣读1 中国的电子商务(转)
http://blog.sina.com.cn/s/blog_3e66af4601015fxi.html 中国电子商务蓄势待发 Chinese e-commerce中国电子商务Pity the par ...
- Android 长时间运行任务说明
android 4.0 后,小米手机需要授权 自动启动 (在安全中心权限里设置),不然AlarmManager设置系统闹钟将不起作用
- python读取文件另存为
fr = open(filename_r,encoding='cp852') w2 = open(filename_w,'a')#a代表追加 w代表重写 for line in fr: w2.writ ...
- (KMP扩展 利用循环节来计算) Cyclic Nacklace -- hdu -- 3746
http://acm.hdu.edu.cn/showproblem.php?pid=3746 Cyclic Nacklace Time Limit: 2000/1000 MS (Java/Others ...
- maven 学习:为什么要使用maven,maven使用过程中的一些参数
Maven是一个基于Java平台的项目构建工具. 设计的出发点: 在进行软件开发的过程中,无论什么项目,采用何种技术,使用何种编程语言,我们要重复相同的开发步骤:编码,编译,测试,生成文档,打包发布. ...
- Java设计模式の单利模式
单利模式:确保一个类最多只有一个实例,并提供一个全局访问点. 经典单利模式创建对象代码 public class Singleton { private static Singleton unique ...
- UniGUI的TUniLoginForm窗口自定义背景色
uniGUI的TUniLoginForm类创建的登录窗口默认是不带颜色,可以自定义css风格来改变背景颜色. 一般是通过在UniServerModule中,在CustcomSS属性中,修改extjs的 ...
- 【TFS 2017】使用浏览器上传文件(TFVC)或者编辑代码,错误提示TF14098,需要对文件有PendChange 权限
从TFS 2015开始,微软在TFS系统中增加了一个非常吸引开发人员的功能,"快速代码编辑器" (Quick Code Editor).使用这个功能,你可以在任何安装了浏览器的设备 ...