[虚树模板] 洛谷P2495 消耗战
[update]
好像有个东西叫笛卡尔树,好像是这样建的.....
inline void build_d() {
stk[top = ] = ;
for(int i = ; i <= n; i++) {
while(top && val[stk[top]] <= val[i]) {
ls[i] = stk[top];
top--;
}
if(ls[i]) {
fa[ls[i]] = i;
}
if(top) {
fa[i] = stk[top];
rs[stk[top]] = i;
}
stk[++top] = i;
}
RT = stk[];
return;
}
题意:给定树上k个点,求切断这些点到根路径的最小代价。∑k <= 5e5
解:虚树。
构建虚树大概是这样的:设加入点与栈顶的lca为y,比较y和栈中第二个元素的DFS序大小关系。
代码如下:
inline bool cmp(const int &a, const int &b) {
return pos[a] < pos[b];
}
inline void build_t() {
std::sort(imp + , imp + k + , cmp);
TP = top = ;
stk[++top] = imp[];
use[imp[]] = Time;
E[imp[]] = ;
for(int i = ; i <= k; i++) {
int x = imp[i], y = lca(x, stk[top]);
if(use[x] != Time) {
use[x] = Time;
E[x] = ;
}
if(use[y] != Time) {
use[y] = Time;
E[y] = ;
}
while(top > && pos[y] <= pos[stk[top - ]]) {
ADD(stk[top - ], stk[top]);
top--;
}
if(stk[top] != y) {
ADD(y, stk[top]);
stk[top] = y;
}
stk[++top] = x;
}
while(top > ) {
ADD(stk[top - ], stk[top]);
top--;
}
RT = stk[top];
return;
}
然后本题建虚树跑DP就行了。注意虚树根节点的DP初值和虚树的边权。
#include <cstdio>
#include <algorithm> typedef long long LL;
const int N = ;
const LL INF = 1e18; struct Edge {
int nex, v;
LL len;
}edge[N << ], EDGE[N << ]; int tp, TP; int e[N], siz[N], stk[N], top, Time, n, fa[N][], k, RT, num, pos[N], pw[N], now[N], imp[N], E[N], d[N], use[N];
LL f[N], small[N][]; inline void ADD(int x, int y, LL z) {
TP++;
EDGE[TP].v = y;
EDGE[TP].len = z;
EDGE[TP].nex = E[x];
E[x] = TP;
return;
} inline void add(int x, int y, LL z) {
top++;
edge[top].v = y;
edge[top].len = z;
edge[top].nex = e[x];
e[x] = top;
return;
} void DFS_1(int x, int father) { // get fa small
fa[x][] = father;
d[x] = d[father] + ;
pos[x] = ++num;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == father) {
continue;
}
small[y][] = edge[i].len;
DFS_1(y, x);
}
return;
} inline int lca(int x, int y) {
if(d[x] > d[y]) {
std::swap(x, y);
}
int t = pw[n];
while(t >= && d[x] < d[y]) {
if(d[fa[y][t]] >= d[x]) {
y = fa[y][t];
}
t--;
}
if(x == y) {
return x;
}
t = pw[n];
while(t >= && fa[x][] != fa[y][]) {
if(fa[x][t] != fa[y][t]) {
x = fa[x][t];
y = fa[y][t];
}
t--;
}
return fa[x][];
} inline bool cmp(const int &a, const int &b) {
return pos[a] < pos[b];
} inline LL getMin(int x, int y) {
LL ans = INF;
int t = pw[d[y] - d[x]];
while(t >= && y != x) {
if(d[fa[y][t]] >= d[x]) {
ans = std::min(ans, small[y][t]);
y = fa[y][t];
}
t--;
}
return ans;
} inline void build_t() {
std::sort(imp + , imp + k + , cmp);
TP = top = ;
stk[++top] = imp[];
use[imp[]] = Time;
E[imp[]] = ;
for(int i = ; i <= k; i++) {
int x = imp[i], y = lca(x, stk[top]);
if(use[x] != Time) {
use[x] = Time;
E[x] = ;
}
if(use[y] != Time) {
use[y] = Time;
E[y] = ;
}
while(top > && pos[y] <= pos[stk[top - ]]) {
ADD(stk[top - ], stk[top], getMin(stk[top - ], stk[top]));
top--;
}
if(stk[top] != y) {
ADD(y, stk[top], getMin(y, stk[top]));
stk[top] = y;
}
stk[++top] = x;
}
while(top > ) {
ADD(stk[top - ], stk[top], getMin(stk[top - ], stk[top]));
top--;
}
RT = stk[top];
return;
} void DFS(int x) {
siz[x] = (now[x] == Time);
LL temp = ;
for(int i = E[x]; i; i = EDGE[i].nex) {
int y = EDGE[i].v;
f[y] = EDGE[i].len;
DFS(y);
siz[x] += siz[y];
if(siz[y]) {
temp += f[y];
}
}
if(now[x] != Time) {
f[x] = std::min(f[x], temp);
}
return;
} void out(int x) {
return;
} int main() {
scanf("%d", &n);
/*if(n > 100) {
return -1;
}*/
int x, y; LL z;
for(int i = ; i < n; i++) {
scanf("%d%d%lld", &x, &y, &z);
add(x, y, z);
add(y, x, z);
}
// get lca min_edge
DFS_1(, );
for(int i = ; i <= n; i++) {
pw[i] = pw[i >> ] + ;
}
for(int j = ; j <= pw[n]; j++) {
for(int i = ; i <= n; i++) {
fa[i][j] = fa[fa[i][j - ]][j - ];
small[i][j] = std::min(small[i][j - ], small[fa[i][j - ]][j - ]);
}
} int m;
scanf("%d", &m);
for(Time = ; Time <= m; Time++) {
scanf("%d", &k);
//printf("\n k = %d \n", k);
for(int i = ; i <= k; i++) {
scanf("%d", &imp[i]);
now[imp[i]] = Time;
}
//printf("input over \n");
build_t();
//out(RT);
f[RT] = getMin(, RT);
DFS(RT);
printf("%lld\n", f[RT]);
} return ;
}
AC代码
[虚树模板] 洛谷P2495 消耗战的更多相关文章
- 【数论】卢卡斯定理模板 洛谷P3807
[数论]卢卡斯定理模板 洛谷P3807 >>>>题目 [题目] https://www.luogu.org/problemnew/show/P3807 [输入格式] 第一行一个 ...
- KMP字符串匹配 模板 洛谷 P3375
KMP字符串匹配 模板 洛谷 P3375 题意 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.(如果 ...
- 洛谷 P2495 [SDOI2011]消耗战(虚树,dp)
题面 洛谷 题解 虚树+dp 关于虚树 了解一下 具体实现 inline void insert(int x) { if (top == 1) {s[++top] = x; return ;} int ...
- 洛谷P2495 [SDOI2011]消耗战(虚树dp)
P2495 [SDOI2011]消耗战 题目链接 题解: 虚树\(dp\)入门题吧.虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是 ...
- 洛谷P2495 [SDOI2011]消耗战(虚树)
题面 传送门 题解 为啥一直莫名其妙\(90\)分啊--重构了一下代码才\(A\)掉-- 先考虑直接\(dp\)怎么做 树形\(dp\)的时候,记一下断开某个节点的最小值,就是从根节点到它的路径上最短 ...
- ●洛谷P2495 [SDOI2011]消耗战
题链: https://www.luogu.org/problemnew/show/P2495题解: 虚树入门,树形dp 推荐博客:http://blog.csdn.net/lych_cys/arti ...
- 树链剖分模板(洛谷P3384)
洛谷P3384 #include <bits/stdc++.h> #define DBG(x) cerr << #x << " = " < ...
- AC日记——[SDOI2011]消耗战 洛谷 P2495
[SDOI2011]消耗战 思路: 建虚树走树形dp: 代码: #include <bits/stdc++.h> using namespace std; #define INF 1e17 ...
- [Bzoj2286][Sdoi2011]消耗战(虚树模板题附讲解)
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4896 Solved: 1824[Submit][Statu ...
随机推荐
- Socket异步通信及心跳包同时响应逻辑分析(最后附Demo)。
有段时间没有更博了,刚好最近在做Socket通信的项目,原理大致内容:[二维码-(加logo)]-->提供主机地址和端口号信息(直接使用[ThoughtWorks.QRCode.dll]比较简单 ...
- checkpoint-BLCR部署和测试(源码)
1. 概述2. 部署过程2.1 源码下载2.2 解压安装2.3 添加库环境2.4 插入内核模块3. 测试3.1 创建测试程序3.2 功能测试4. 参考博客 1. 概述 checkpoint 2. 部署 ...
- MFS+Keepalived双机高可用热备方案操作记录
基于MFS的单点及手动备份的缺陷,考虑将其与Keepalived相结合以提高可用性.在Centos下MooseFS(MFS)分布式存储共享环境部署记录这篇文档部署环境的基础上,只需要做如下改动: 1) ...
- 《Gogoing》Alpha版会议总结
一.开会的过程 首先大家对自己的任务进行了汇报,然后大家就当前最需要解决的问题提出解决方案,最后相互鼓励,相互帮助,探讨下一步该怎么做. 二.讨论的问题 百度地图API代码和界面代码为什么对接不上? ...
- “数学口袋精灵”App的第三个Sprint计划----开发日记(第一天12.7~第十天12.16)
“数学口袋精灵”第三个Sprint计划----第一天 项目进度: 基本完成一个小游戏,游戏具有:随机产生算式,判断对错功能.通过轻快的背景音乐,音效,给玩家提供一个良好的氛围. 任务分配: 冯美欣: ...
- Spring Cloud Zipkin
Zipkin the idea is from the googlge paper:Dapper https://yq.aliyun.com/articles/60165 https://www.e4 ...
- Effective C++(第三版)笔记 ---- 第一部分让自己习惯C++
内容从侯捷译版的<Effective C++>(第三版)摘录 条款一 C++作为一个多种范式融合的语言,可以看成是语言的联邦,它包含了一下四种主要的次语言: C.C++以C为基础,很多时候 ...
- Linux 忘记root密码
1 将系统重启,读秒的时候按下任意键就会出现如下图菜单界面 2 进入上图菜单界面之后,按e键就可以进入grub的编辑模式 3 选择第二行 kernel开头,再按 e 键进入该行的编辑界面中,然后在出现 ...
- CentOS 关闭烦人的屏保
1. VNC连接到服务器 2.打开 system tools - settings 在power处 将 Power Saving 设置改一下
- Oracle数据库 查看表是否是 索引组织表的方法
1. 最近在工作过程中发现 一个表插入很慢 以为是索引组织表, 所以一直有点纠结 但是发现 产品里面是没有IOT的 于是找了下公司的OCP 问了下 如何查看 就是 user_tables 视图里面的一 ...