洛谷P4719 动态dp
动态DP其实挺简单一个东西。
把DP值的定义改成去掉重儿子之后的DP值。
重链上的答案就用线段树/lct维护,维护子段/矩阵都可以。其实本质上差不多...
修改的时候在log个线段树上修改。轻儿子所在重链的线段树的根拿去更新父亲的DP值。
#include <cstdio>
#include <algorithm> const int N = , INF = 0x3f3f3f3f; template <class T> inline void read(T &x) {
x = ;
char c = getchar();
bool f = ;
while(c < '' || c > '') {
if(c == '-') {
f = ;
}
c = getchar();
}
while(c >= '' && c <= '') {
x = (x << ) + (x << ) + c - ;
c = getchar();
}
if(f) {
x = (~x) + ;
}
return;
} struct Edge {
int nex, v;
}edge[N << ]; int tp; // 0 0 0
// 1 0 1
// 2 1 0
// 3 1 1 int top[N], e[N], siz[N], pos[N], id[N], val[N], fa[N], son[N], d[N], num, n, len[N];
int f[N][], seg[N * ][], tot, ls[N * ], rs[N * ], rt[N]; inline void add(int x, int y) {
tp++;
edge[tp].v = y;
edge[tp].nex = e[x];
e[x] = tp;
return;
} void DFS_1(int x, int f) { // son siz fa d
fa[x] = f;
d[x] = d[f] + ;
siz[x] = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == f) {
continue;
}
DFS_1(y, x);
siz[x] += siz[y];
if(siz[y] > siz[son[x]]) {
son[x] = y;
}
}
return;
} void DFS_2(int x, int f) { // pos id top
top[x] = f;
pos[x] = ++num;
id[num] = x;
len[x] = ;
if(son[x]) {
DFS_2(son[x], f);
len[x] = len[son[x]] + ;
}
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == son[x] || y == fa[x]) {
continue;
}
DFS_2(y, y);
}
return;
} inline void pushup(int o) {
int l = ls[o], r = rs[o];
seg[o][] = std::max(seg[l][] + seg[r][], seg[l][] + seg[r][]);
seg[o][] = std::max(seg[o][], seg[l][] + seg[r][]); seg[o][] = std::max(seg[l][] + seg[r][], seg[l][] + seg[r][]);
seg[o][] = std::max(seg[o][], seg[l][] + seg[r][]); seg[o][] = std::max(seg[l][] + seg[r][], seg[l][] + seg[r][]);
seg[o][] = std::max(seg[o][], seg[l][] + seg[r][]); seg[o][] = std::max(seg[l][] + seg[r][], seg[l][] + seg[r][]);
seg[o][] = std::max(seg[o][], seg[l][] + seg[r][]);
return;
} inline void build(int l, int r, int &o) {
if(!o) {
o = ++tot;
}
if(l == r) {
seg[o][] = f[id[r]][];
seg[o][] = -INF;
seg[o][] = -INF;
seg[o][] = val[id[r]] + f[id[r]][];
return;
}
int mid = (l + r) >> ;
build(l, mid, ls[o]);
build(mid + , r, rs[o]);
pushup(o);
return;
} void change(int p, int l, int r, int o) {
//printf("change -- : %d %d %d \n", p, l, r);
if(l == r) {
seg[o][] = f[id[r]][];
seg[o][] = -INF;
seg[o][] = -INF;
seg[o][] = val[id[r]] + f[id[r]][];
//printf("%d = %d + %d \n", id[r], val[id[r]], f[id[r]][1]);
return;
}
int mid = (l + r) >> ;
if(p <= mid) {
change(p, l, mid, ls[o]);
}
else {
change(p, mid + , r, rs[o]);
}
pushup(o);
//printf("%d %d \n", id[l], id[r]);
//printf("%d %d %d %d \n", seg[o][0], seg[o][1], seg[o][2], seg[o][3]);
return;
} inline void change(int x, int v) {
//printf("change %d %d \n", x, v);
val[x] = v;
while(x) {
int xx = top[x];
if(fa[xx]) {
int temp = std::max(seg[rt[xx]][], seg[rt[xx]][]);
f[fa[xx]][] -= temp;
f[fa[xx]][] -= std::max(std::max(seg[rt[xx]][], seg[rt[xx]][]), temp);
}
//printf("ch %d %d %d \n", x, xx, id[pos[xx] + len[xx] - 1]);
change(pos[x], pos[xx], pos[xx] + len[xx] - , rt[xx]);
if(fa[xx]) {
int temp = std::max(seg[rt[xx]][], seg[rt[xx]][]);
f[fa[xx]][] += temp;
f[fa[xx]][] += std::max(std::max(seg[rt[xx]][], seg[rt[xx]][]), temp);
}
x = fa[xx];
}
return;
} int main() {
int m;
read(n); read(m);
for(int i = ; i <= n; i++) {
read(val[i]);
}
for(int i = , x, y; i < n; i++) {
read(x); read(y);
add(x, y);
add(y, x);
}
DFS_1(, );
DFS_2(, );
for(int i = ; i <= n; i++) {
int x = id[n + - i];
if(top[x] == x) {
build(pos[x], pos[x] + len[x] - , rt[x]);
if(fa[x]) {
int temp = std::max(seg[rt[x]][], seg[rt[x]][]);
f[fa[x]][] += temp;
f[fa[x]][] += std::max(std::max(seg[rt[x]][], seg[rt[x]][]), temp);
}
}
} for(int i = , x, y; i <= m; i++) {
read(x); read(y);
change(x, y);
int a = std::max(seg[rt[]][], seg[rt[]][]);
int b = std::max(seg[rt[]][], seg[rt[]][]);
printf("%d\n", std::max(a, b));
} return ;
}
AC代码
还有noip最后一题,虽然正解是倍增DP但是显然写动态DP啊...
注意树剖和线段树别写错了..没开O2少用std的函数
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath> typedef long long LL;
const int N = ;
const LL INF = 1e17; template <class T> inline void read(T &x) {
x = ;
char c = getchar();
while(c < '' || c > '') {
c = getchar();
}
while(c >= '' && c <= '') {
x = (x << ) + (x << ) + c - ;
c = getchar();
}
return;
} struct Edge {
int nex, v;
}edge[N * ]; int tp; LL val[N], f[N * ][][], Val[N][];
int e[N], n, m;
int fa[N], top[N], pos[N], id[N], siz[N], son[N], num, d[N], ed[N]; // tree div
int tot, ls[N * ], rs[N * ], rt[N]; // segment tree
char str[]; inline void add(int x, int y) {
tp++;
edge[tp].v = y;
edge[tp].nex = e[x];
e[x] = tp;
return;
} void DFS_1(int x, int f) { // fa son siz d
fa[x] = f;
siz[x] = ;
d[x] = d[f] + ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == f) {
continue;
}
DFS_1(y, x);
siz[x] += siz[y];
if(siz[y] > siz[son[x]]) {
son[x] = y;
}
}
//printf("son %d = %d \n", x, son[x]);
//printf("siz %d = %d \n", x, siz[x]);
return;
} void DFS_2(int x, int f) { // top pos id
pos[x] = ++num;
top[x] = f;
id[num] = x;
ed[f] = num;
//printf("x = %d ed %d = %d \n", x, f, ed[f]);
if(son[x]) {
DFS_2(son[x], f);
}
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == fa[x] || y == son[x]) {
continue;
}
DFS_2(y, y);
}
return;
} inline LL mymin(LL x, LL y) {
return x < y ? x : y;
} inline void exmin(LL &a, LL b) {
a > b ? a = b : ;
return;
} inline void pushup(int o) {
int l = ls[o], r = rs[o];
f[o][][] = INF;
exmin(f[o][][], f[l][][] + f[r][][]);
exmin(f[o][][], f[l][][] + f[r][][]);
exmin(f[o][][], f[l][][] + f[r][][]);
f[o][][] = INF;
exmin(f[o][][], f[l][][] + f[r][][]);
exmin(f[o][][], f[l][][] + f[r][][]);
exmin(f[o][][], f[l][][] + f[r][][]);
f[o][][] = INF;
exmin(f[o][][], f[l][][] + f[r][][]);
exmin(f[o][][], f[l][][] + f[r][][]);
exmin(f[o][][], f[l][][] + f[r][][]);
f[o][][] = INF;
exmin(f[o][][], f[l][][] + f[r][][]);
exmin(f[o][][], f[l][][] + f[r][][]);
exmin(f[o][][], f[l][][] + f[r][][]);
return;
} void build(int l, int r, int &o) {
if(!o) {
o = ++tot;
}
if(l == r) {
// init
int x = id[r];
f[o][][] = Val[x][];
f[o][][] = INF;
f[o][][] = INF;
f[o][][] = val[x] + Val[x][];
return;
}
int mid = (l + r) >> ;
build(l, mid, ls[o]);
build(mid + , r, rs[o]);
pushup(o);
return;
} inline int lca(int x, int y) {
while(top[x] != top[y]) {
if(d[top[x]] <= d[top[y]]) {
y = fa[top[y]];
}
else {
x = fa[top[x]];
}
}
return (d[x] < d[y]) ? x : y;
} inline bool link(int x, int y) {
int z = lca(x, y);
return std::abs(d[x] - d[y]) == && (z == x || z == y);
} inline void change(int p, int v, int l, int r, int o) {
//printf("change %d %d %d %d \n", p, v, l, r);
if(l == r) {
if(v) {
f[o][][] = INF;
}
else {
f[o][][] = INF;
}
return;
}
int mid = (l + r) >> ;
if(p <= mid) {
change(p, v, l, mid, ls[o]);
}
else {
change(p, v, mid + , r, rs[o]);
}
pushup(o);
return;
} inline void update(int p, int l, int r, int o) {
if(l == r) {
int x = id[r];
f[o][][] = Val[x][];
f[o][][] = val[x] + Val[x][];
return;
}
int mid = (l + r) >> ;
if(p <= mid) {
update(p, l, mid, ls[o]);
}
else {
update(p, mid + , r, rs[o]);
}
pushup(o);
return;
} inline void change(int x, int a) {
int xx = x;
while(x) {
if(fa[top[x]]) {
LL temp = mymin(f[rt[top[x]]][][], f[rt[top[x]]][][]);
Val[fa[top[x]]][] -= temp;
Val[fa[top[x]]][] -= mymin(mymin(f[rt[top[x]]][][], f[rt[top[x]]][][]), temp);
}
if(x != xx)
update(pos[x], pos[top[x]], ed[top[x]], rt[top[x]]);
else
change(pos[x], a, pos[top[x]], ed[top[x]], rt[top[x]]);
if(fa[top[x]]) {
LL temp = mymin(f[rt[top[x]]][][], f[rt[top[x]]][][]);
Val[fa[top[x]]][] += temp;
Val[fa[top[x]]][] += mymin(mymin(f[rt[top[x]]][][], f[rt[top[x]]][][]), temp);
}
x = fa[top[x]];
}
return;
} inline void recover(int x) {
while(x) {
if(fa[top[x]]) {
LL temp = mymin(f[rt[top[x]]][][], f[rt[top[x]]][][]);
Val[fa[top[x]]][] -= temp;
Val[fa[top[x]]][] -= mymin(mymin(f[rt[top[x]]][][], f[rt[top[x]]][][]), temp);
}
update(pos[x], pos[top[x]], ed[top[x]], rt[top[x]]);
if(fa[top[x]]) {
LL temp = mymin(f[rt[top[x]]][][], f[rt[top[x]]][][]);
Val[fa[top[x]]][] += temp;
Val[fa[top[x]]][] += mymin(mymin(f[rt[top[x]]][][], f[rt[top[x]]][][]), temp);
}
x = fa[top[x]];
}
return;
} int main() { //freopen("in.in", "r", stdin);
//freopen("my.out", "w", stdout);
read(n); read(m);
scanf("%s", str);
for(register int i = ; i <= n; i++) {
read(val[i]);
}
for(register int i = , x, y; i < n; i++) {
read(x); read(y);
add(x, y); add(y, x);
}
// prework
DFS_1(, );
DFS_2(, );
// build
for(register int a = n; a >= ; a--) {
int x = id[a];
if(top[x] == x) {
build(pos[x], ed[x], rt[x]);
if(fa[x]) {
int father = fa[x];
LL temp = mymin(f[rt[x]][][], f[rt[x]][][]);
Val[father][] += temp;
Val[father][] += mymin(mymin(f[rt[x]][][], f[rt[x]][][]), temp);
}
}
} for(register int i = , x, a, y, b; i <= m; i++) {
scanf("%d%d%d%d", &x, &a, &y, &b);
if(!a && !b && link(x, y)) {
puts("-1");
continue;
}
change(x, a);
change(y, b);
printf("%lld\n", mymin(mymin(f[rt[]][][], f[rt[]][][]), mymin(f[rt[]][][], f[rt[]][][])));
recover(x);
recover(y);
} return ;
}
AC代码
洛谷P4719 动态dp的更多相关文章
- 洛谷P4719 动态DP —— 动态DP(树剖+矩乘)
题目:https://www.luogu.org/problemnew/show/P4719 感觉这篇博客写得挺好:https://blog.csdn.net/litble/article/detai ...
- 洛谷P4719 【模板】动态dp(ddp LCT)
题意 题目链接 Sol 动态dp板子题.有些细节还没搞懂,待我研究明白后再补题解... #include<bits/stdc++.h> #define LL long long using ...
- 洛谷 P4719 【模板】动态dp【动态dp】
是动态dp的板子 大致思想就是用g[u]来表示不包含重链转移的dp值,然后用线段树维护重链,这样线段树的根就相当于这条重链的top的真实dp值 每次修改的时候,修改x点会影响到x到根的真实dp值,但是 ...
- 洛谷P4719 【模板】"动态 DP"&动态树分治
[模板]"动态 DP"&动态树分治 第一道动态\(DP\)的题,只会用树剖来做,全局平衡二叉树什么的就以后再学吧 所谓动态\(DP\),就是在原本的\(DP\)求解的问题上 ...
- 洛谷教主花园dp
洛谷-教主的花园-动态规划 题目描述 教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价 ...
- 洛谷P1393 动态逆序对(CDQ分治)
传送门 题解 听别人说这是洛谷用户的双倍经验啊……然而根本没有感觉到……因为另外的那题我是用树状数组套主席树做的……而且莫名其妙感觉那种方法思路更清晰(虽然码量稍稍大了那么一点点)……感谢Candy大 ...
- 洛谷 p6858 深海少女与胖头鱼 洛谷月赛 期望dp
洛谷10月月赛 2 t2 深海少女与胖头鱼 题目链接 参考资料:洛谷10月赛2讲评ppt; 本篇题解考完那天就开始写,断断续续写到今天才写完 本题作为基础的期望dp题,用来学习期望dp还是很不错的 ( ...
- 洛谷P4719 【模板】动态dp
https://www.luogu.org/problemnew/show/P4719 大概就是一条链一条链的处理(“链”在这里指重链),对于每一条链,对于其上每一个点,先算出它自身和所有轻儿子的贡献 ...
- 2019.01.04 洛谷P4719 【模板】动态dp(链分治+ddp)
传送门 ddpddpddp模板题. 题意简述:给你一棵树,支持修改一个点,维护整棵树的最大带权独立集. 思路: 我们考虑如果没有修改怎么做. 貌似就是一个sbsbsb树形dpdpdp,fi,0f_{i ...
随机推荐
- ASP.NET Core 入门教程 7、ASP.NET Core MVC 分部视图入门
一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)分部视图简介 ASP.NET Core MVC (Razor)分部视图基础教程 ASP.NET Core MVC (Raz ...
- tofixed方法 四舍五入
tofixed方法 四舍五入 toFixed() 方法可把 Number 四舍五入为指定小数位数的数字.例如将数据Num保留2位小数,则表示为:toFixed(Num):但是其四舍五入的规则与数学中的 ...
- MySQL游标循环取出空值的BUG
早上同事要我写个MySQL去除重复数据的SQL,想起来上次写过一篇MySQL去除重复数据的博客,使用导入导出加唯一索引实现的,但是那种方式对业务影响较大,所以重新写一个存储过程来删重复数据,这一写就写 ...
- Windows server 2008R2远程桌面3389端口修改方法技巧
windows server的服务器远程桌面默认端口号是3389,在工作中经常使用远程桌面连接服务器,但是这也是常常被黑客利用的端口号,但是如何修改掉默认端口,预防被黑客利用呢? 可以如下操作配置:很 ...
- 英语口语练习系列-C12-不了解
词汇 air [eə(r)] n. 空气 fresh air 新鲜的空气 warm air 暖暖的空气 I like to air the room. 我喜欢给房间通气. on the air 正在播 ...
- spring MVC处理请求过程
spring MVC处理请求过程 首先看一个整体图 简单说下各步骤: handlerMapping handlerMapping将请求映射到处理器,即图中的HandlerExecutionChain. ...
- Linux-基础学习(六)-Redis的进阶学习
1. redis的进阶操作 1.1 redis的订阅操作 发布订阅的命令 PUBLISH channel msg 将信息 message 发送到指定的频道 channel SUBSCRIBE chan ...
- redis分页
模仿的https://www.cnblogs.com/dee0912/p/4612183.html 第一步连接redis后进行添加数据 require_once '../redis/redis.php ...
- Openwrt自定义CGI实现
此文已由作者吴志勐授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 安装uhttpd. 在编译openwrt前,输入make memuconfig,查找Network -> ...
- 在Fabric ChainCode中导入第三方包(以状态机为例)
在企业级应用开发中,经常会涉及到流程和状态,而有限状态机(FSM)则是对应的一种简单实现,如果复杂化,就上升到Workflow和BPM了.我们在Fabric ChainCode的开发过程中,也很可能涉 ...