【洛谷4719】 动态dp(树链剖分,dp,矩阵乘法)
前言
其实我只是为了过掉模板而写的ddp,实际应用被吊着锤
Solution
并不想写详细的过程
一句话过程:将子树中轻儿子的贡献挂到这个点上面来
详细版:(引用yyb)
总结一下的话,大致的过程是这样子的:首先我们考虑我们的转移方程,发现能够将其改写为矩乘的形式,那么我们首先将转移改为矩乘。我们把轻链和重链的转移分开考虑。这样子想,我们的重链被我们单独拎了出来,每个重链上都挂上了若干轻儿子,显然轻儿子对于重链上的独立集的选择是没有影响的,换而言之,如果轻儿子的贡献考虑完之后,那么等价于链上每个点选或者不选有一个权值,求最大独立集。而对于链上的这个东西,是可以直接用线段数维护矩阵支持修改和查询的,那么这题就只需要这么做就好了。即只修改这个点到达根节点上的所有轻链对于父亲的贡献,对于重儿子的贡献先暂时不考虑,每次线段树查询矩阵乘积即可求解出每个点的矩阵,就可以快速求解答案了
代码实现
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
inline int gi(){
int f=1,sum=0;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
const int N=100010;
const ll Inf=1e18+10;
int a[N],front[N],nxt[N<<1],to[N<<1],cnt,n,m,dep[N],son[N],siz[N],fa[N],top[N],dfn[N],Time,id[N],bot[N];
void Add(int u,int v){
to[++cnt]=v;nxt[cnt]=front[u];front[u]=cnt;
}
struct matrix{
ll a[2][2];
ll*operator [](int x){return a[x];};
matrix operator*(matrix b)const{
matrix c;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++){
c[i][j]=0;
for(int k=0;k<2;k++)
c[i][j]=max(c[i][j],a[i][k]+b[k][j]);
}
return c;
}
}t[N<<2],tmp[N];
void dfs1(int u,int f){
dep[u]=dep[f]+1;siz[u]=1;fa[u]=f;
for(int i=front[u];i;i=nxt[i]){
int v=to[i];
if(v==f)continue;
dfs1(v,u);
siz[u]+=siz[v];if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int tp){
top[u]=tp;dfn[u]=++Time;id[Time]=u;
if(son[u]){dfs2(son[u],tp),bot[u]=bot[son[u]];}
else bot[u]=u;
for(int i=front[u];i;i=nxt[i]){
int v=to[i];
if(v==fa[u] || v==son[u])continue;
dfs2(v,v);
}
}
ll f[N][2];
void dp(int u){
f[u][1]=a[u];
for(int i=front[u];i;i=nxt[i]){
int v=to[i];
if(v==fa[u])continue;
dp(v);
f[u][0]+=max(f[v][1],f[v][0]);
f[u][1]+=f[v][0];
}
}
void build(int o,int l,int r){
if(l==r){
int u=id[l];int g0=0,g1=a[u];
for(int i=front[u];i;i=nxt[i]){
int v=to[i];
if(v==fa[u] || v==son[u])continue;
g0+=max(f[v][1],f[v][0]);g1+=f[v][0];
}
tmp[l]=t[o]=(matrix){g0,g0,g1,-Inf};
return;
}
int mid=(l+r)>>1;
build(o<<1,l,mid);build(o<<1|1,mid+1,r);
t[o]=t[o<<1]*t[o<<1|1];
}
//------------以上是dp+树剖-----------------------------------------------
void Modify(int o,int l,int r,int p){
if(l==r){t[o]=tmp[l];return;}
int mid=(l+r)>>1;
if(p<=mid)Modify(o<<1,l,mid,p);
else Modify(o<<1|1,mid+1,r,p);
t[o]=t[o<<1]*t[o<<1|1];
}
matrix query(int o,int l,int r,int posl,int posr){
if(posl==l && posr==r)return t[o];
int mid=(l+r)>>1;
if(mid>=posr)return query(o<<1,l,mid,posl,posr);
else if(mid<posl)return query(o<<1|1,mid+1,r,posl,posr);
return query(o<<1,l,mid,posl,mid)*query(o<<1|1,mid+1,r,mid+1,posr);
}
matrix ask(int x){return query(1,1,n,dfn[top[x]],dfn[bot[x]]);}
void Modify(int u,int w){
tmp[dfn[u]][1][0]+=w-a[u];a[u]=w;
while(u){
matrix a=ask(top[u]);Modify(1,1,n,dfn[u]);
matrix b=ask(top[u]);
u=fa[top[u]];if(!u)break;
tmp[dfn[u]][0][1]=(tmp[dfn[u]][0][0]+=max(b[0][0],b[1][0])-max(a[0][0],a[1][0]));
tmp[dfn[u]][1][0]+=b[0][0]-a[0][0];
}
}
int main(){
n=gi();m=gi();
for(int i=1;i<=n;i++)a[i]=gi();
for(int i=1;i<n;i++){int u=gi(),v=gi();Add(u,v);Add(v,u);}
dfs1(1,0);dfs2(1,1);dp(1);build(1,1,n);
matrix t;
while(m--){
int u=gi(),x=gi();
Modify(u,x);
t=ask(1);
printf("%lld\n",max(t[0][0],t[1][0]));
}
return 0;
}
【洛谷4719】 动态dp(树链剖分,dp,矩阵乘法)的更多相关文章
- 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)
题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...
- BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...
- 洛谷P3459 [POI2007]MEG-Megalopolis [树链剖分]
题目传送门 MEG 题目描述 Byteotia has been eventually touched by globalisation, and so has Byteasar the Postma ...
- 洛谷 P3950 部落冲突 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例1 输出样例1 输入样例2 输出样例2 输入样例3 输出样例3 说明 思路 AC代码 总结 题面 题目链接 P3 ...
- 洛谷 P2486 [SDOI2011]染色 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...
- 洛谷 P4211 [LNOI2014]LCA (树链剖分+离线)
题目:https://www.luogu.org/problemnew/solution/P4211 相当难的一道题,其思想难以用言语表达透彻. 对于每个查询,区间[L,R]中的每个点与z的lca肯定 ...
- 洛谷P3038 牧草种植 [树链剖分]
题目传送门 牧草种植 题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirec ...
- 洛谷P4114 Qtree1(树链剖分+线段树)
传送门 LCT秒天秒地用什么树剖 这题可以算是树剖的比较裸的题目了 把每一条边的权值下放到他两边的点中深度较深的那个 然后直接用树剖+线段树带进去乱搞就可以了 //minamoto #include& ...
- 洛谷$P4211\ [LNOI2014]\ LCA$ 树链剖分+线段树
正解:树剖+线段树 解题报告: 传送门$QwQ$ 看到$dep[lca]$啥的就想到之前托腮腮$CSP$模拟$D1T3$的那个套路,,, 然后试下这个想法,于是$dep[lca(x,y)]=\sum_ ...
- 6.3 省选模拟赛 Decompose 动态dp 树链剖分 set
LINK:Decompose 看起来很难 实际上也很难 考验选手的dp 树链剖分 矩阵乘法的能力. 容易列出dp方程 暴力dp 期望得分28. 对于链的情况 容易发现dp方程可以转矩阵乘法 然后利用线 ...
随机推荐
- fusioncharts 破解方法(转载)
FusionCharts是一个Flash的图表组件,它可以用来制作数据动画图表,其中动画效果用的是Adobe Flash 8 (原Macromedia Flash的)制作的flash , Fusion ...
- MySql删除表、数据
程度从强到弱 1.drop table tb drop将表格直接删除,没有办法找回 2.truncate (table) tb 删除表中的所有数据,不能与where一起使用 ...
- MacOs执行SQL出错(mysql)
上次修改过root密码之后,刚启动,执行sql就报错了. 错误是: Reset MySQL root password using ALTER USER statement after install ...
- HHvm建站环境搭建方法:Nginx,Mariadb,hhvm及lnmp/lamp安装部署
HHVM起源于Facebook公司,是一个开源的PHP虚拟机,使用JIT的编译方式以及其他技术,让PHP代码的执行性能大幅提升.HHVM提升PHP性能的途径,采用的方式就是替代Zend引擎来生成和执行 ...
- 将Win7笔记本设置成WiFi热点(无线路由器)
查看是否能启动WiFi网卡: S1:运行cmd命令,打开命令提示符窗口(以管理员身份运行). S2:在命令行输入:netsh wlan show drivers. 若“支持的承载网络”后为“是”,则可 ...
- 80% UI 初学者走过的弯路,你走了几条?
关于UI 对于初学UI设计的人而言,可能对UI具体是做什么,或者自己是否能顺利转行胜任这样的岗位存在一定的顾虑,今天我们就来重点说说UI是做什么的,以及学UI到有哪些需要避免的弯路. 1.UI设计是做 ...
- js点击添加
1.点击变色 <div id="dd" style="width:100px;height: 100px;background-color: #ccc"& ...
- maven 打包 OutOfMemoryError
maven 打包 OutOfMemoryError [ERROR] Java heap space -> [Help 1] [ERROR] [ERROR] To see the full sta ...
- 使用delphi 开发多层应用(二十四)KbmMW 的消息方式和创建WIB节点
KbmMW 中支持基于UDP的消息广播,也支持TCP/IP hub/spoke 方式,还有 基于UDP或者TCP/IP 的点对点的消息传输. 1.基于UDP的消息广播
- 2018.09.17 atcoder Tak and Cards(背包)
传送门 背包经典题. 直接f[i][j]f[i][j]f[i][j]表示选i张牌和为j的方案数. 最后统计答案就行了. 代码: #include<bits/stdc++.h> #defin ...