【jzoj 5336】Timi / 提米树(DP)
Timi / 提米树
题目链接:jzoj 5336
题目大意
给你一棵树,树上点有权值。
然后树的分数是它们叶子节点权值和减去所有相邻叶子的代价。
相邻叶子是两个叶子节点,它们在 dfs 序之间没有别的叶子节点。代价则是它们之间的路径上(不包含这两个叶子节点)最大的点权值。
然后你可以对树进行若干次剪枝,剪枝是如果一个点的所有儿子都是叶子节点,你就可以把它的所有儿子删去。
要你给出能有的最大分数。
思路
首先我们来看一些性质:
它可以无限次操作剪枝,所以你可以相当于对一个点剪枝就是把它的儿子部分全部减掉。
然后不难发现你要让两个点成为相邻的叶子,一定要它们在原来树的某两个相邻叶子的路径上。
然后我们不难想出 O(n2)O(n^2)O(n2) 的暴力。
fif_ifi 为 dfs 序为 1∼i1\sim i1∼i 的处理好的最优分数。
然后不难想到枚举叶子,然后枚举叶子之间的路径,然后路径两边各自枚举,然后转移。
然后考虑优化,我们把转移的式子列出来:
fi=max(fj−max(gi,gj))+aif_i=\max(f_j-\max(g_i,g_j))+a_ifi=max(fj−max(gi,gj))+ai
(gig_igi 是 iii 到 LCA 的路径中权值最大的点权,aia_iai 则是点权)
不难想到可以预处理出 ggg,以及 f−gf-gf−g
显然 ggg 有单调性,可以把 ggg 分成 gi>gjg_i>g_jgi>gj 和 gi⩽gjg_i\leqslant g_jgi⩽gj 两种。(i,ji,ji,j 分别代表左右两边的点)
那就枚举右边,找左边的分界点就搞个指针就可以了。
代码
#include<cstdio>
#include<vector>
#define INF 0x3f3f3f3f3f3f3f3fusing namespace std;int n, fa[100001], deg[100001];
int a[100001], x, y, dfn[100001];
int Leaf[100001], tmp, f[100001];
int X[100001], Y[100001], s[100002];
int g[100002], left, right, num, ans;
vector <int> son[100001];void dfs(int now) {dfn[now] = ++tmp;if (!son[now].size()) Leaf[++Leaf[0]] = now;for (int i = 0; i < son[now].size(); i++) {deg[son[now][i]] = deg[now] + 1;dfs(son[now][i]);}
}void get_first() {x = Leaf[1];while (x != 1) {f[x] = a[x];x = fa[x];}a[x] = a[x];
}void get_road() {X[0] = Y[0] = 0;int xx = x, yy = y;while (deg[xx] > deg[yy]) {X[++X[0]] = xx;xx = fa[xx];}while (deg[yy] > deg[xx]) {Y[++Y[0]] = yy;yy = fa[yy];}while (xx != yy) {X[++X[0]] = xx;Y[++Y[0]] = yy;xx = fa[xx]; yy = fa[yy];}
}void get_ans() {x = Leaf[Leaf[0]];while (x != 1) {ans = max(ans, f[x]);x = fa[x];}ans = max(ans, f[x]);
}int main() {scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);scanf("%d", &x);for (int j = 1; j <= x; j++) {scanf("%d", &y);son[i].push_back(y);fa[y] = i;}}deg[1] = 1;dfs(1);get_first();for (int i = 2; i <= Leaf[0]; i++) {x = Leaf[i - 1]; y = Leaf[i];get_road();s[X[0] + 1] = 0;for (int i = X[0]; i >= 0; i--)//先跑出后缀s[i] = max(s[i + 1], a[fa[X[i]]]);g[0] = -INF;for (int i = 1; i <= X[0]; i++)//跑出原来路径只有左边的部分g[i] = max(g[i - 1], f[X[i]] - s[i]);left = right = -INF; num = X[0];for (int i = Y[0]; i >= 1; i--) {right = max(right, a[fa[Y[i]]]);while (num && right > s[num]) {//找到分界点left = max(left, f[X[num]]);num--;}f[Y[i]] = max(left - right, g[num]) + a[Y[i]];//左边和右边选优的那个}}get_ans();printf("%d", ans);return 0;
}
【jzoj 5336】Timi / 提米树(DP)相关推荐
- [BZOJ2125]最短路(圆方树DP)
题意:仙人掌图最短路. 算法:圆方树DP,$O(n\log n+Q\log n)$ 首先建出仙人掌圆方树(与点双圆方树的区别在于直接连割边,也就是存在圆圆边),然后考虑点u-v的最短路径,显然就是:在 ...
- 【BZOJ1040】【codevs1423】骑士,第一次的基环外向树DP
传送门1 传送门2 思路: 好题 比较简单的DP思路 之前没写过基环树DP,第一次搞真心orz 我们发现这些元素是具有从属关系的 也就是说如果对"厌恶的骑士"两两相互连边,那么问题 ...
- 51nod1812树的双直径(换根树DP)
传送门:http://www.51nod.com/Challenge/Problem.html#!#problemId=1812 题解:头一次写换根树DP. 求两条不相交的直径乘积最大,所以可以这样考 ...
- 基环树DP(bzoj 1040: [ZJOI2008]骑士)
树:n个点n-1条边的连通图 基环树:n个点n条边的连通图,也就是一个环套着多棵树 基环树DP:找到环上任意相邻两点,断掉这两点之间的边,就形成了一棵树 之后对这两点分别进行一次树形DP即可 例题: ...
- P1295 [TJOI2011]书架(线段树dp)
P1295 [TJOI2011]书架(线段树dp) 我好菜 先考虑普通dp: d p i = m i n ( d p j + m a x ( h j + 1 , h j + 2 - , h i ) ) ...
- 【BZOJ1124】Mafia(POI2008)-环套树DP
测试地址:Mafia 做法: 本题需要用到环套树DP. 按照题目构图,很显然是我们很熟悉的环套树森林.接下来我们进行分析,最后活下来一些什么人是合法的呢?观察发现,一个人的目标如果是自己那就必死,而没 ...
- 洛谷P2495 [SDOI2011]消耗战(虚树dp)
P2495 [SDOI2011]消耗战 题目链接 题解: 虚树\(dp\)入门题吧.虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是 ...
- 【暖*墟】#动态规划# 基环树DP的学习与练习
因为弃置了 四边形不等式优化 ,所以DP的任务还剩下 基环树DP / 插头DP / 动态DP 当然,树形DP / 状压DP / 数位DP / 斜率优化DP 也还是要练习的...... 一 . 基环树的 ...
- HDU 3016 Man Down (线段树+dp)
HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- jzoj 5814. 【NOIP提高A组模拟2018.8.14】树 dp+lca
Description 梦游中的你来到了一棵 N 个节点的树上. 你一共做了 Q 个梦, 每个梦需要你从点 u 走到 点 v 之后才能苏醒, 由于你正在梦游, 所以每到一个节点后,你会在它连出去的边中 ...
最新文章
- 高效的密码攻击方法:彩虹表
- Windows 2003 server 服务器集群实例
- 如何在服务器端完善游戏的用户体验
- linux tar.gz文件安装
- 获取本机IP_考虑多网卡的情况
- 读《财务自由之路》教会我的道理
- linux系统下网络连接不上的问题
- mysql+磁盘i+o+优化_浅析MySQL数据库磁盘I/O调整优化
- UPPERERR.txt
- FreeBSD 安装axel提高ports的安装速度
- android期末大作业_关于大学期末的一点碎碎念
- Datawhale编程学习之排序(3)
- MD5加密、Base64加密解密
- java debug怎么用_debug怎么用
- Linux 安装 VMware Player
- 视力测试软件正确吗,体检视力测试
- 阿里巴巴大数据之路-数据整合管理体系
- linux清除ip地址命令,ip 命令 和ifconfig 命令 删除IP
- 赛制出炉!西门子白帽黑客大赛吹响集结号
- 王道考研——计算机组成原理(第一章 计算机系统概述)
热门文章
- linux svn cleanup 用法,svn操作-clean up死循环
- cad2010背景怎么调成黑色_3D错觉立体画到底是怎么画出来的?
- 论文笔记:Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
- html注册cab包,OCX控件打包成CAB并实现数字签名过程
- Jenkins linux 操作系统一键部署多节点
- 【转载】Linux查看日志
- 优色专显教你led显示屏诺瓦刷屏教程
- 图像处理:灰度变换与图像增强
- 网页img 居中办法
- java制作报表统计_统计报表制作,怎样做报表统计