CF980E The Number Games
给定一棵大小为 \(n\) 的树,第 \(i\) 个点的点权为 \(2^i\) ,删掉 \(k\) 个点及其连边,使得剩下的点组成一个连通块,且权值和最大,输出要删掉的点
\(n,\ k\leq10^6\)
贪心,倍增,dfs序
很容易想到一个贪心:不断删掉能被删除且权值最小的点,用堆实现
但很明显这是错的:局部最优 \(\neq\) 全局最优
因为点权为 \(2^i\) ,所以与其选择 \(1,\ 2,\ \cdots,\ i-1\) 不如选 \(i\) 这一个点
考虑这样一个 \(O(n^2)\) 贪心:从大往小确定不被删的点。以 \(n\) 为根,若当前枚举到的节点可选则将根到这个点的路径上的所有点都选掉
可以发现,问题转化为了快速求出一个点是否可选,并标记路径
因为最多会标记 \(n-1\) 条路径,所以可以暴力标记,倍增查询
时间复杂度 \(O(n\log n)\) ,空间复杂度 \(O(n\log n)\)
原操作还有另一种实现方式:树状数组维护dfs序上每个点的距离,标记路径时修改子树内答案
这种做法虽然略显繁琐,但是不失为一种常用的高效算法
时间复杂度 \(O(n\log n)\) ,空间复杂度 \(O(n)\)
倍增代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
int n, k, fa[21][maxn]; bool vis[maxn];
vector <int> e[maxn];
void dfs(int u, int f) {
fa[0][u] = f;
for (int i = 1; i < 21; i++) {
fa[i][u] = fa[i - 1][fa[i - 1][u]];
}
for (int v : e[u]) {
if (v != f) dfs(v, u);
}
}
int lca(int u) {
int res = 0;
for (int i = 20; ~i; i--) {
if (!vis[fa[i][u]]) {
u = fa[i][u], res |= 1 << i;
}
}
return res;
}
int main() {
scanf("%d %d", &n, &k);
for (int i = 1, u, v; i < n; i++) {
scanf("%d %d", &u, &v);
e[u].push_back(v), e[v].push_back(u);
}
dfs(n, 0), vis[0] = 1;
int tmp = n - k;
for (int i = n; i; i--) {
int t = lca(i);
if (t < tmp) {
int cur = i;
while (!vis[cur]) {
vis[cur] = 1, tmp--, cur = fa[0][cur];
}
}
}
for (int i = 1; i < n; i++) {
if (!vis[i]) printf("%d ", i);
}
return 0;
}
dfs序+树状数组代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
int n, k, now, a[maxn], c[maxn], sz[maxn], fa[maxn], tid[maxn], dep[maxn]; bool vis[maxn];
vector <int> e[maxn];
void upd(int pos, int x) {
for (; pos <= n; pos += pos & -pos) {
c[pos] += x;
}
}
int query(int pos) {
int res = 0;
for (; pos; pos &= pos - 1) {
res += c[pos];
}
return res;
}
int dfs(int u, int f) {
a[++now] = u, tid[u] = now, fa[u] = f, dep[u] = dep[f] + 1;
for (int v : e[u]) {
if (v != f) sz[u] += dfs(v, u);
}
return ++sz[u];
}
int main() {
scanf("%d %d", &n, &k);
for (int i = 1, u, v; i < n; i++) {
scanf("%d %d", &u, &v);
e[u].push_back(v), e[v].push_back(u);
}
dfs(n, 0), upd(1, -1);
for (int i = 1; i <= n; i++) {
upd(i, dep[a[i]] - dep[a[i - 1]]);
}
int tmp = n - k; vis[0] = 1;
for (int i = n; i; i--) {
if (query(tid[i]) < tmp) {
for (int cur = i; !vis[cur]; tmp--, vis[cur] = 1, cur = fa[cur]) {
upd(tid[cur], -1), upd(tid[cur] + sz[cur], 1);
}
}
}
for (int i = 1; i < n; i++) {
if (!vis[i]) printf("%d ", i);
}
return 0;
}
CF980E The Number Games的更多相关文章
- CF980E The Number Games【树链剖分/线段树】
CF980E The Number Games 题意翻译 Panel 国将举办名为数字游戏的年度表演.每个省派出一名选手. 国家有 n 个编号从 1 到 n 的省,每个省刚好有一条路径将其与其他省相连 ...
- Codeforces 980 E. The Number Games
\(>Codeforces \space 980 E. The Number Games<\) 题目大意 : 有一棵点数为 \(n\) 的数,第 \(i\) 个点的点权是 \(2^i\) ...
- Codeforces 980E The Number Games 贪心 倍增表
原文链接https://www.cnblogs.com/zhouzhendong/p/9074226.html 题目传送门 - Codeforces 980E 题意 $\rm Codeforces$ ...
- codeforces 980E The Number Games
题意: 给出一棵树,要求去掉k个点,使得剩下的还是一棵树,并且要求Σ(2^i)最大,i是剩下的节点的编号. 思路: 要使得剩下的点的2的幂的和最大,那么肯定要保住大的点,这是贪心. 考虑去掉哪些点的话 ...
- Codeforces 980E The Number Games - 贪心 - 树状数组
题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗有$n$个点的树,$i$号点的权值是$2^{i}$要求删去$k$个点,使得剩下的点仍然连通,并且总权值和最大,问删去的所有点的编号. ...
- Codeforces Round #480 (Div. 2) E - The Number Games
题目大意:给你n个点的一棵树, 每个点的权值为2^i ,让你删掉k个点使得剩下的权值和最大. 思路:这题还是比较好想的, 我们反过来考虑, 剩下一个的情况肯定是选第n个点,剩下两个 我们肯定优先考虑第 ...
- The Number Games CodeForces - 980E (树, 贪心)
链接 大意: 给定$n$节点树, 求删除$k$个节点, 使得删除后还为树, 且剩余点$\sum{2^i}$尽量大 维护一个集合$S$, 每次尽量添加最大的点即可 这样的话需要支持求点到集合的最短距离, ...
- cf round 480E The Number Games
题意:给一棵树,点$i$的点权是$2^i$,你需要删掉$k$个点,使得剩下的点连通的情况下剩下的点权值和最大. $k \leq n \leq 10^6$ 如果考虑删哪些点,是不好考虑的,会出问题. 反 ...
- POJ1336 The K-League[最大流 公平分配问题]
The K-League Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 715 Accepted: 251 Descri ...
随机推荐
- java map集合 --遍历
1.Map 遍历: Map<Integer, String> map = new HashMap<Integer, String>(); map.put(1, "a& ...
- phpcms调用指定文章内容模型的ID
一.使用GET调用Phpcms V9指定id页面数据方法 {pc:get sql="SELECT * FROM cmsyou_news WHERE id='55'" cache=& ...
- Elasticsearch Elasticsearch入门指导
Elasticsearch入门指导 By:授客 QQ:1033553122 1. 开启elasticsearch服务器 1 2. 基本概念 2 <1> 集群(Cluster) 2 < ...
- Android为TV端助力 http下载视频到指定目录
public void httpget(String uri){ HttpURLConnection connection = null; FileOutputStream fos = null; F ...
- wangEditor更改默认高度
在使用WangEditor时觉得高度太低,默认是300px;想调下高度,借鉴https://blog.csdn.net/qq_31384551/article/details/83240188, 网址 ...
- 架构师成长之路-基于android fragment通信的面向对象的万能接口
前言 开发一个app时,常用Activity和Fragment,由于操作方便Fragment越来越受欢迎,这样就避免不了Activity和Fragment.Fragment和Fragment之间的通信 ...
- MySQL Host is blocked because of many connection errors 解决方法
应用日志提示错误:create connection error, url: jdbc:mysql://10.45.236.235:3306/db_wang?useUnicode=true&c ...
- Linux CFS调度器之队列操作--Linux进程的管理与调度(二十七)
1. CFS进程入队和出队 完全公平调度器CFS中有两个函数可用来增删队列的成员:enqueue_task_fair和dequeue_task_fair分别用来向CFS就绪队列中添加或者删除进程 2 ...
- Lua保留指定小数位数
默认会四舍五入 比如:%0.2f 会四舍五入后,保留小数点后2位 print(string.format("%.1f",0.26)) ---会输出0.3,而不是0.2 Lua保留一 ...
- CVE-2017-8464 分析
目录 CVE-2017-8464(stuxnet 3.0) 分析 0xFF 前言 0x00 分析工具 0x01 漏洞复现 1).生成一个DLL用于测试 2).构造一个恶意的lnk二进制文件 3).RU ...