题目大意:给你一颗$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模板的更多相关文章

  1. 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)

    洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\)​​​​​.我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...

  2. 洛谷P4719 【模板】"动态 DP"&动态树分治

    [模板]"动态 DP"&动态树分治 第一道动态\(DP\)的题,只会用树剖来做,全局平衡二叉树什么的就以后再学吧 所谓动态\(DP\),就是在原本的\(DP\)求解的问题上 ...

  3. 洛谷p1052过河 路径压缩+dp

    洛谷 P1052 过河 思路部分可以看这篇博客 我将在这里对其进行一些解释与补充 首先我们先看题 乍一看 这不是模板题吗 然后开开心心的敲了一个简单dp上去 #include<iostream& ...

  4. 洛谷2344 奶牛抗议(DP+BIT+离散化)

    洛谷2344 奶牛抗议 本题地址:http://www.luogu.org/problem/show?pid=2344 题目背景 Generic Cow Protests, 2011 Feb 题目描述 ...

  5. Lightning Conductor 洛谷P3515 决策单调性优化DP

    遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森. 先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬. 废话不多说,看题: 题目大意 已知一个长度为n的序 ...

  6. 洛谷P1541 乌龟棋(四维DP)

    To 洛谷.1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游 ...

  7. 【洛谷】P1052 过河【DP+路径压缩】

    P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙 ...

  8. 【题解】洛谷P1052 [NOIP2005TG] 过河(DP+离散化)

    题目来源:洛谷P1052 思路 一开始觉得是贪心 但是仔细一想不对 是DP 再仔细一看数据不对 有点大 如果直接存下的话 显然会炸 那么就需要考虑离散化 因为一步最大跳10格 那么我们考虑从1到10都 ...

  9. 洛谷1736(二维dp+预处理)

    洛谷1387的进阶版,但很像. 1387要求是“全为1的正方形”,取dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1]))吧?这个有“只有对 ...

  10. bzoj3295 洛谷P3157、1393 动态逆序对——树套树

    题目:bzoj3295 https://www.lydsy.com/JudgeOnline/problem.php?id=3295 洛谷 P3157(同一道题) https://www.luogu.o ...

随机推荐

  1. db2中如何获取当前日期前一周的日期

    SELECT CURRENT_DATE - (DAYOFWEEK(CURRENT_DATE) - 2 + (ROW_NUMBER() OVER (ORDER BY 1) ) ) DAY AS resu ...

  2. 使用RSA进行信息加密解密的WebService示例

    使用RSA进行信息加密解密的WebService示例 按:以下文字涉及RSA对WebService传递的数据的加密解密,如果您已经熟知RSA或是有其它更好的方法请不要往下看以免浪费时间. WebSer ...

  3. myeclipse svn 插件去除已经保存的密码方法

    myeclipse svn 插件去除已经保存的密码方法   删除掉C:\Documents and Settings\hao\Application Data\Subversion\auth\svn. ...

  4. 【Linux】Jenkins配置和使用(二)

    摘要 本章介绍Jenkins的简单使用,关于Jenkins的安装,参照[Linux]Jenkins安装(一) 事例说明:在linux环境下,安装的jenkins,集成svn,tomcat的环境,项目是 ...

  5. centos7 rabbitmq安装以及应用

    安装单机rabbitmq   1.安装erlang cd /usr.local yum install wget yum install net-tools wget http://erlang.or ...

  6. PTA第五次作业

    #include<stdio.h> #include<math.h> int main () { int n,m,i,j,a; scanf("%d",&am ...

  7. C# 编写最小化时隐藏为任务栏图标的Window appllication

    1.设置窗体属性showinTask=false 2.加notifyicon控件notifyIcon1,为控件notifyIcon1的属性Icon添加一个icon图标. 3.添加窗体最小化事件(首先需 ...

  8. Devexpress VCL Build v2014 vol 14.2.1 beta发布

    已经快到2015 年了. 14.2.1 beta 才出来了. 还好,有一些新东西. 官网地址 VCL Gauge Control Designed to clearly convey informat ...

  9. mysql 查询表 的所有字段名称

    select COLUMN_NAME from information_schema.COLUMNS where table_name = 'your_table_name' and table_sc ...

  10. spring boot2.0冷知识

    首先,Spring Boot 2.0.0 要求 Java 8 或更高版本,不再支持 Java 6 和 7. 在 Spring Boot 2.0 中,许多配置属性已被重命名或被删除,相应地,开发者需要升 ...