【洛谷】P4643 【模板】动态dp

题解

在冬令营上听到冬眠的东西,现在都是板子了猫锟真的是好毒瘤啊(雾)

(立个flag,我去thusc之前要把WC2018T1乱搞过去= =)

好的,我们可以参考猫锟的动态动态dp的课件,然后你发现你什么都看不懂(菜啊

但是我们仔细看一看,可以发现用数据结构维护矩阵,那么我们尝试构造一个矩阵

\(\begin{bmatrix} \ g_{u,0} & g_{u,0}\\ g_{u,1} & 0 \end{bmatrix} \begin{bmatrix} f_{son[u],0}\\ f_{son[u],1} \end{bmatrix} = \begin{bmatrix} f_{u,0}\\ f_{u,1} \end{bmatrix}\)
其中\(g_{u,0}\)表示不选u,对于u的子树,除了u的重儿子所在子树,u的轻儿子最大独立集是多少
\(g_{u,1}\)表示选了u
\(f_{u,0}\)表示不选u,以u为根的子树最大独立集是多少
\(f_{u,1}\)表示选了u,以u为根的子树最大独立集是多少

这个矩阵的运算不是加法和乘法,而是加法和取max
也就是\(c_{i,j} = max(a_{i,k} + b_{k,j})\)
也是满足结合律的

这样我们就可以用一个树链剖分来维护这些矩阵了

注意一下,合并矩阵的时候是左右合并,但是乘法的时候一定先从右边乘
举个例子,我们的运算实际是这样的
一条链:
3 - 4 - 5
3是4的父亲,4是5的父亲
\(\begin{bmatrix} \ g_{3,0} & g_{3,0}\\ g_{3,1} & 0 \end{bmatrix} \begin{bmatrix} \ g_{4,0} & g_{4,0}\\ g_{4,1} & 0 \end{bmatrix} \begin{bmatrix} f_{5,0}\\ f_{5,1} \end{bmatrix} = \begin{bmatrix} f_{3,0}\\ f_{3,1} \end{bmatrix}\)
也就是5先和4的矩阵结合,再和3的矩阵结合

实际上写代码的时候,既然每一条链的最后一定是一个叶子节点,我们就可以直接把f0设成0,f1设成0去做矩阵乘法,乘上这条链上所有的矩阵作为链顶的f值

代码

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map>
//#define ivorysi
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define mo 974711
#define RG register
#define MAXN 100005
#define debug
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {res = 0;char c = getchar();T f = 1;while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9') {res = res * 10 + c - '0';c = getchar();}res *= f;
}
template<class T>
void out(T x) {if(x < 0) putchar('-'),x = -x;if(x >= 10) out(x / 10);putchar('0' + x % 10);
}
const int MOD = 1000000007;
int mul(int a,int b) {return 1LL * a * b % MOD;
}
int inc(int a,int b) {a = a + b;if(a >= MOD) a -= MOD;return a;
}int fpow(int x,int c) {int res = 1,t = x % MOD;while(c) {if(c & 1) res = mul(res,t);t = mul(t,t);c >>= 1;}return res;
}
int N,Q;
int64 val[MAXN],g[MAXN][2],f[MAXN][2];
int top[MAXN],btm[MAXN],dfn[MAXN],fa[MAXN],dep[MAXN],son[MAXN],idx,siz[MAXN],L[MAXN],pos[MAXN];
int cnt = 0;
struct node {int to,next;
}E[MAXN * 2];
int head[MAXN],sumE;
struct tr_node {int l,r;int64 M[2][2];
}tr[MAXN * 4];
void add(int u,int v) {E[++sumE].to = v;E[sumE].next = head[u];head[u] = sumE;
}
void dfs1(int u) {dep[u] = dep[fa[u]] + 1;siz[u] = 1;for(int i = head[u] ; i ; i = E[i].next) {int v = E[i].to;if(v != fa[u]) {fa[v] = u;dfs1(v);siz[u] += siz[v];if(siz[v] > siz[son[u]]) son[u] = v;}}
}
void dfs2(int u) {dfn[u] = ++idx;L[idx] = u;if(!top[u]) {top[u] = u;}if(son[u]) {top[son[u]] = top[u];dfs2(son[u]);btm[u] = btm[son[u]]; }g[u][1] = val[u];g[u][0] = 0;for(int i = head[u] ; i ; i = E[i].next) {int v = E[i].to;if(v != son[u] && v != fa[u]) {dfs2(v);g[u][0] += max(f[v][0],f[v][1]);g[u][1] += max(0LL,f[v][0]);}}f[u][1] = g[u][1] + max(f[son[u]][0],0LL);f[u][0] = g[u][0] + max(f[son[u]][1],f[son[u]][0]);if(!son[u]) btm[u] = u;
}
void update(int u) {int L = u << 1,R = u << 1 | 1;tr[u].M[0][0] = max(tr[L].M[0][0] + tr[R].M[0][0],tr[L].M[0][1] + tr[R].M[1][0]);tr[u].M[0][1] = max(tr[L].M[0][0] + tr[R].M[0][1],tr[L].M[0][1] + tr[R].M[1][1]);tr[u].M[1][0] = max(tr[L].M[1][0] + tr[R].M[0][0],tr[L].M[1][1] + tr[R].M[1][0]);tr[u].M[1][1] = max(tr[L].M[1][0] + tr[R].M[0][1],tr[L].M[1][1] + tr[R].M[1][1]);
}
void build(int u,int l,int r) {tr[u].l = l;tr[u].r = r;if(l == r) {int v = L[l];tr[u].M[0][0] = g[v][0];tr[u].M[0][1] = g[v][0];tr[u].M[1][0] = g[v][1];tr[u].M[1][1] = 0;pos[v] = u;return ;}int mid = (l + r) >> 1;build(u << 1,l,mid);build(u << 1 | 1,mid + 1,r);update(u);
}
void Query(int u,int L,int R,int64 &f0,int64 &f1) {if(tr[u].l == L && tr[u].r == R) {int64 x = max(f0 + tr[u].M[0][0],f1 + tr[u].M[0][1]);int64 y = max(f0 + tr[u].M[1][0],f1 + tr[u].M[1][1]);f0 = x;f1 = y;return;}int mid = (tr[u].l + tr[u].r) >> 1;if(R <= mid) Query(u << 1,L,R,f0,f1);else if(L > mid) Query(u << 1 | 1,L,R,f0,f1);else {Query(u << 1 | 1,mid + 1,R,f0,f1);Query(u << 1,L,mid,f0,f1);}
}
void Change(int x) {int t = pos[x] >> 1;while(t) {update(t);t >>= 1;}
}
void Change_tr(int x) {while(1) {int a = top[x];if(fa[a] != 0) {g[fa[a]][0] -= max(f[a][0],f[a][1]);g[fa[a]][1] -= max(f[a][0],0LL);}f[a][0] = 0;f[a][1] = 0;Query(1,dfn[top[x]],dfn[btm[x]],f[a][0],f[a][1]);if(fa[a] == 0) break;g[fa[a]][0] += max(f[a][0],f[a][1]);g[fa[a]][1] += max(f[a][0],0LL);x = fa[a];tr[pos[x]].M[0][0] = tr[pos[x]].M[0][1] = g[x][0];tr[pos[x]].M[1][0] = g[x][1];tr[pos[x]].M[1][1] = 0;Change(x);}
}
void Init() {read(N);read(Q);for(int i = 1 ; i <= N ; ++i) read(val[i]);int u,v;for(int i = 1 ; i < N ; ++i) {read(u);read(v);add(u,v);add(v,u);}dfs1(1);dfs2(1);build(1,1,N);
}
void Solve() {int x;int64 y;while(Q--) {++cnt;read(x);read(y);g[x][1] = g[x][1] - val[x] + y;tr[pos[x]].M[1][0] = g[x][1];val[x] = y;Change(x);Change_tr(x);out(max(f[1][0],f[1][1]));enter;}
}
int main() {
#ifdef ivorysifreopen("f1.in","r",stdin);
#endifInit();Solve();return 0;
}

转载于:https://www.cnblogs.com/ivorysi/p/9118007.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

让 CentOS 启动时不启动桌面服务

[日期&#xff1a;2012-11-03] 来源&#xff1a;Linux社区 作者&#xff1a;kandyer [字体&#xff1a;大 中 小] 修改/etc/inittab文件&#xff0c;将 id:5:initdefault: 改为 id:3:initdefault: Linux 系统任何时候都运行在一个指定的运行级上&#xff0c;并且不同的运…

bzoj2721樱花——质因数分解

题目&#xff1a;https://www.lydsy.com/JudgeOnline/problem.php?id2721 可以知道 x 和 y 一定都大于 n! &#xff0c;不妨把 y 表示为 n!t &#xff1b; 那么 1/x 1/y 1/x 1/(n!t) 1/n! &#xff1b; 整理一下&#xff0c;最终变成&#xff1a;x (n!)/t 1 &#xff1b…

带有WildFly Swarm的远程JMS

我再次在博客上谈论WildFly群&#xff1f; 简短的版本是&#xff1a;我需要对远程JMS访问进行测试&#xff0c;并且拒绝设置复杂的功能&#xff08;如完整的应用程序服务器&#xff09;。 这个想法是要有一个简单的WildFly Swarm应用程序&#xff0c;该应用程序配置了队列和主题…

CentOS,重启的常用命令

重启命令 Linux中常用的关机和重新启动命令有shutdown、halt、reboot以及init&#xff0c;它们都可以达到关机和重新启动的目的&#xff0c;但是每个命令的内部工作过程是不同的&#xff0c;下面将逐一进行介绍。 1. shutdown shutdown命令用于安全关闭Linux系统。有些用户会…

nosql怎么使用_使用NoSQL实施实体服务–第5部分:使用云提高自治性

nosql怎么使用在之前的文章中&#xff0c;我讨论了如何通过结合使用Java Web Services &#xff0c; Java EE和CouchDB NoSQL数据库为产品构建SOA“实体”服务。 在本系列的最后一篇文章中&#xff0c;我将利用我已经创建的一些技术资产&#xff0c;并使用一些流行的SOA模式实现…

串口MSComm控件五种不同校验方式对数据收发的影响

(2008-09-10 14:50:00) http://blog.sina.com.cn/s/blog_470eccc60100arq7.html串口MSComm控件有五种校验方式&#xff0c;分别是无校验&#xff08;None&#xff09;&#xff0c;奇校验&#xff08;Odd&#xff09;&#xff0c;偶校验&#xff08;Even&#xff09;&#xff0c…

利刃 MVVMLight 3:双向数据绑定

利刃 MVVMLight 3&#xff1a;双向数据绑定 原文:利刃 MVVMLight 3&#xff1a;双向数据绑定上篇我们已经了解了MVVM的框架结构和运行原理。这里我们来看一下伟大的双向数据绑定。说到双向绑定&#xff0c;大家比较熟悉的应该就是AngularJS了&#xff0c;几乎所有的AngularJS 系…

使用Java扫描DynamoDB项目

在之前的文章中&#xff0c;我们介绍了如何查询DynamoDB数据库 查询DynamoDB第1部分 查询DynamoDB第2部分 。 除了发出查询之外&#xff0c;DynamoDB还提供扫描功能。 扫描所做的是获取您在DynamoDB表上可能拥有的所有项目。 因此&#xff0c;扫描不需要任何基于我们的分区键…

实战 SSH 端口转发

from: http://www.ibm.com/developerworks/cn/linux/l-cn-sshforward/ 通过本文的介绍&#xff0c;读者可以从中了解到如何应用 SSH 端口转发机制来解决日常工作 / 生活中的一些问题。学会在非安全环境下使用端口转发来加密网络应用&#xff0c;保护个人隐私以及重要商业信息。…

627.Swap Salary-(LeetCode之Database篇)

问题描述 给出下面的表&#xff0c;名为salary。 idnamesexsalary1Am25002Bf15003Cm55004Df500要求执行一个UPDATE语句&#xff0c;将表转换成下面的样子。 idnamesexsalary1Af25002Bm15003Cf55004Dm500即m与f交换位置。 问题解决 下面我使用SQL中的case when来解决问题。…

unix/linux命令“ls -l”选项输出结果详解

from: http://hi.baidu.com/hoxily/item/12e2a02d03f77e0942634a8e unix/linux命令“ls -l”选项输出结果详解 下面是我在lucidubuntu使用”ls -l /”的结果&#xff1a; hoxilyubuntulucid:/$ ll / total 96 drwxr-xr-x 22 root root 4096 2012-02-06 20:10 ./ drwxr-xr-x 2…

delayqueue_在DelayQueue中更改延迟,从而更改顺序

delayqueue因此&#xff0c;我正在考虑构建一个简单的对象缓存&#xff0c;该缓存在给定时间后会使对象过期。 显而易见的机制是使用Java并发包中的DelayedQueue类。 但是我想知道是否有可能在将对象添加到队列后更新延迟。 看一下Delayed接口&#xff0c;似乎没有充分的理由不…

使用Amalgamate将C/C++项目合并成一个.h/.c[pp]文件

简述 C/C开源库一般是一堆的头文件和源文件&#xff0c;做到声明和实现分离&#xff0c;减小单个模块大小&#xff0c;这在设计上是很好的&#xff0c;但是用起来稍显麻烦。在网上看到有好心人推荐了一个开源工具Amalgamate&#xff0c;专门用来对C/C的头文件和源文件进行合并用…

Java数组排序解码

排序是我们在计算机科学中学习的第一个算法。 排序是一个非常有趣的领域&#xff0c;它有大约20多种算法&#xff0c;而且总是很难确定哪种算法最好。 排序算法的效率是根据所需的时间和所需的空间来衡量的。 一些时间气泡排序是最好的&#xff0c;因为它没有空间需求&#xff…

linux下删除乱码文件名的方法

from: http://www.jb51.net/LINUXjishu/32910.html linux下删除乱码文件名, 不废话: 1. ls -i 列出文件的节点ID, 如: 123456789 2. find ./ -inum 123456789 -print -exec rm -rf {} \; 批量删除: for n in 123456789 987654321;do find . -inum $n -exec rm -f {} \;…

A - Beautiful Matrix

Problem description Youve got a 5  5 matrix, consisting of 24 zeroes and a single number one. Lets index the matrix rows by numbers from 1 to 5 from top to bottom, lets index the matrix columns by numbers from 1 to 5 from left to right. In one move, you …

MATLAB中用FDATool设计滤波器及使用

from: http://blog.sina.com.cn/s/blog_3e4367660100nyz1.html 1. 在Matlab中键入fdatool运行Filter Design and Analysis Tool。具体使用请参见Matlab Help中的Signal Processing Toolbox->FDATool。 2. 在fdatool工具中应该注意的几个问题&#xff1a;(a)Fstop&#xf…

电商等大型网站高可用,高负载架构借鉴方案(转载)

任何一个大型网站都是经历用户积累然后成长&#xff0c;从一台服务器到多台服务器才能构架支撑网站现有数据、用户、页面请求等。大型网站(如淘宝、京东等)的系统架构并不是开始设计就具备完整的高性能、高可用、安全等特性&#xff0c;它总是随着用户量的增加&#xff0c;业务…

《Hadoop实战》的笔记-2、Hadoop输入与输出

from: http://book.douban.com/annotation/17068812/ 这一问题本书只在第三章简单说了一下读写HDFS&#xff0c;虽然能说明问题&#xff0c;但是本着第一遍读书应该把书读厚的原则&#xff0c;我觉得很有必要自行展开一番。再说凡是万变不离其宗嘛&#xff0c;任何程序都是从“…

复制模式和扩展模式_扩展剂:模式还是反模式?

复制模式和扩展模式扩展器模式在最近几年变得很流行&#xff0c;甚至已经在OSGi标准&#xff08;例如&#xff0c;蓝图服务和Web应用程序规范&#xff09;中使用。 在处女座&#xff0c;我们从一开始就与扩展程序一起工作&#xff0c;但是尽管它们具有优势&#xff0c;但它们仍…