luoguP4719 【模板】动态 DP 线段树+树链剖分+矩阵乘法+动态DP
题目描述
给定一棵n个点的树,点带点权。
有m次操作,每次操作给定x,y,表示修改点x的权值为y。
你需要在每次操作之后求出这棵树的最大权独立集的权值大小。
输入输出格式
输入格式:
第一行,n,m分别代表点数和操作数。
第二行,V1,V2,...,Vn,代表n个点的权值。
接下来n−1行,x,y,描述这棵树的n−1条边。
接下来m行,x,y,修改点x的权值为y。
输出格式:
对于每个操作输出一行一个整数,代表这次操作后的树上最大权独立集。
保证答案在int范围内
Matrix operator*(Matrix a,Matrix b)
{
Matrix c;
c[0][0]=max(a[0][0]+b[0][0],a[0][1]+b[1][0]);
c[0][1]=max(a[0][0]+b[0][1],a[0][1]+b[1][1]);
c[1][0]=max(a[1][0]+b[0][0],a[1][1]+b[1][0]);
c[1][1]=max(a[1][0]+b[0][1],a[1][1]+b[1][1]);
return c;
}
我们用矩阵乘法维护每一次链上的转移.

Code:
#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin)
#define maxn 300000
#define lson (now<<1)
#define rson ((now<<1)|1)
#define ll long long
const ll inf = 1e17;
using namespace std;
int hd[maxn],to[maxn],nex[maxn],V[maxn],hson[maxn],fa[maxn],dfn[maxn], ln[maxn],F[maxn][2],siz[maxn],top[maxn],bot[maxn];
int edges,tim,n,Q;
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void dfs1(int u,int ff)
{
siz[u]=1,fa[u]=ff;
for(int i=hd[u];i;i=nex[i])
{
if(to[i]==ff) continue;
dfs1(to[i],u);
siz[u]+=siz[to[i]];
if(siz[to[i]] > siz[hson[u]]) hson[u]=to[i];
}
}
void dfs2(int u,int tp)
{
top[u]=tp,ln[++tim]=u,dfn[u]=tim;
if(hson[u])
dfs2(hson[u], tp), bot[u]=bot[hson[u]];
else
bot[u]=u;
for(int i=hd[u];i;i=nex[i])
{
if(to[i]==fa[u]||to[i]==hson[u]) continue;
dfs2(to[i],to[i]);
}
}
void dfs(int u)
{
F[u][0]=0,F[u][1]=V[u];
for(int i=hd[u];i;i=nex[i])
{
if(to[i]==fa[u]) continue;
dfs(to[i]);
F[u][0]+=max(F[to[i]][1],F[to[i]][0]);
F[u][1]+=F[to[i]][0];
}
}
struct Matrix
{
ll a[2][2];
ll*operator[](int x){ return a[x]; }
}t[maxn<<1],tmp[maxn<<1];
Matrix operator*(Matrix a,Matrix b)
{
Matrix c;
c[0][0]=max(a[0][0]+b[0][0],a[0][1]+b[1][0]);
c[0][1]=max(a[0][0]+b[0][1],a[0][1]+b[1][1]);
c[1][0]=max(a[1][0]+b[0][0],a[1][1]+b[1][0]);
c[1][1]=max(a[1][0]+b[0][1],a[1][1]+b[1][1]);
return c;
}
void Build(int now,int l,int r)
{
if(l==r)
{
int u=ln[l];
ll g0=0,g1=V[u];
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==fa[u]||v==hson[u]) continue;
g0+=max(F[v][0],F[v][1]);
g1+=F[v][0];
}
t[now]=tmp[l]=(Matrix) {g0,g0,g1,-inf};
return;
}
int mid=(l+r)>>1;
Build(lson,l,mid),Build(rson,mid+1,r);
t[now]=t[lson]*t[rson];
}
void Modify(int now,int l,int r,int p)
{
if(l==r)
{
t[now]=tmp[l];
return;
}
int mid=(l+r)>>1;
if(p<=mid) Modify(lson,l,mid,p);
else Modify(rson,mid+1,r,p);
t[now]=t[lson]*t[rson];
}
Matrix Query(int now,int l,int r,int L,int R)
{
if(L==l&&r==R) return t[now];
int mid=(l+r)>>1;
if(R<=mid) return Query(lson,l,mid,L,R);
if(L>mid) return Query(rson,mid+1,r,L,R);
return Query(lson,l,mid,L,mid)*Query(rson,mid+1,r,mid+1,R);
}
void Update(int u,int w)
{
tmp[dfn[u]][1][0]+=w-V[u],V[u]=w;
while(u)
{
Matrix a=Query(1,1,n,dfn[top[u]],dfn[bot[u]]);
Modify(1,1,n,dfn[u]);
Matrix b=Query(1,1,n,dfn[top[u]],dfn[bot[u]]);
u=fa[top[u]];
if(!u) break;
int x = dfn[u];
ll g0=a[0][0],g1=a[1][0],f0=b[0][0],f1=b[1][0];
tmp[x][0][0]=tmp[x][0][1]=tmp[x][0][0]+max(f0,f1)-max(g0,g1);
tmp[x][1][0]=tmp[x][1][0]+f0-g0;
}
}
int main()
{
// setIO("input");
scanf("%d%d",&n,&Q);
for(int i=1;i<=n;++i) scanf("%d",&V[i]);
for(int i=1,u,v;i<n;++i)
{
scanf("%d%d",&u,&v),add(u,v),add(v,u);
}
dfs1(1,0),dfs2(1,1),dfs(1),Build(1,1,n);
while(Q--)
{
int x,w;
scanf("%d%d",&x,&w);
Update(x,w);
Matrix ans=Query(1,1,n,dfn[1],dfn[bot[1]]);
printf("%lld\n",max(ans[0][0],ans[1][0]));
}
return 0;
}
luoguP4719 【模板】动态 DP 线段树+树链剖分+矩阵乘法+动态DP的更多相关文章
- 51nod 1462 树据结构 | 树链剖分 矩阵乘法
题目链接 51nod 1462 题目描述 给一颗以1为根的树. 每个点有两个权值:vi, ti,一开始全部是零. Q次操作: 读入o, u, d o = 1 对u到根上所有点的vi += d o = ...
- 形态形成场(矩阵乘法优化dp)
形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 ...
- 【bzoj1778】[Usaco2010 Hol]Dotp 驱逐猪猡 矩阵乘法+概率dp+高斯消元
题目描述 奶牛们建立了一个随机化的臭气炸弹来驱逐猪猡.猪猡的文明包含1到N (2 <= N <= 300)一共N个猪城.这些城市由M (1 <= M <= 44,850)条由两 ...
- 斐波那契数列 矩阵乘法优化DP
斐波那契数列 矩阵乘法优化DP 求\(f(n) \%1000000007\),\(n\le 10^{18}\) 矩阵乘法:\(i\times k\)的矩阵\(A\)乘\(k\times j\)的矩 ...
- 线段树&数链剖分
傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...
- 【清澄A1333】【整体二分+二维树状数组】矩阵乘法(梁盾)
试题来源 2012中国国家集训队命题答辩 问题描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入格式 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共 ...
- 矩阵乘法优化DP复习
前言 最近做毒瘤做多了--联赛难度的东西也该复习复习了. Warning:本文较长,难度分界线在"中场休息"部分,如果只想看普及难度的可以从第五部分直接到注意事项qwq 文中用(比 ...
- [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】
题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...
- 矩阵乘法优化DP
本文讲一下一些基本的矩阵优化DP的方法技巧. 定义三个矩阵A,B,C,其中行和列分别为$m\times n,n \times p,m\times p$,(其中行是从上往下数的,列是从左往右数的) $C ...
随机推荐
- [bzoj2850]巧克力王国_KD-Tree
巧克力王国 bzoj-2850 题目大意:给出n块巧克力,每块巧克力都有自己的两个参数x和y和本身的价值val,询问:m个人,每个人有两个系数和一个限度a,b,和c.求所有ax+by<=c的巧克 ...
- F2BPM 开发Api与RESTfull应用服务Api 层次关系及示例
目前越来越多的企业架构解决方案更加趋向于基于http协议“微服务”访问跨系统调用,而不使用统传的WebService调用,即通过RESTfull方式进行交互,更加轻量整合调用更加方便.本文档中所有F2 ...
- IntelliJ IDEA 在左右两侧出现Project、Maven Project等导航按钮
IntelliJ IDEA 在左右两侧出现Project.Maven Project等导航按钮 选中 View > Tool Buttons 可以查看Project.Maven Project等 ...
- StringIndexOutOfBoundsException
<span style="font-family:Microsoft YaHei;font-size:14px;">public class StringIndexBo ...
- uva 11605 - Lights inside a 3d Grid(概率)
option=com_onlinejudge&Itemid=8&page=show_problem&problem=2652" style=""& ...
- grails一对多双向关联
前面分享了一些学习grails的心得,可是grails的知识还远不止这些,这次整理了一点有关grails一对多双向关联关系的知识.我认为这样的关联用的地方太多了,这次准备的样例是城市和区域的相关样例. ...
- Jmeter压测问题_Non HTTP response code: java.net.ConnectException
负载机压测,线程500,服务器根本无压力,负载机本身发的请求都是失败的 Sample result如下: Thread Name: 考勤(考勤提交) 1-255 Sample Start: 2018- ...
- 【SDOI2008】【BZOJ2049】Cave 洞穴勘測
Description 辉辉热衷于洞穴勘測.某天,他依照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘測,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成.而且每条通道连接了恰好 ...
- Oracle GoldenGate从oracle db 到非oracle db的初始化数据同步的方法
非oracle db以 sqlserver为样例说明: 我的思路 A :oracle db 生产 B: oracle db 中间机 C: sqlserver db 目的端 A-> B-> ...
- WINDOWS下配置SVN代码管理
服务器端使用 visualsvn server,客户端使用tortoiseSvn. 一.服务器端 1.首先,下载visualsvn server,安装到服务器.下载地址: http://www.vis ...