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的更多相关文章

  1. CF980E The Number Games【树链剖分/线段树】

    CF980E The Number Games 题意翻译 Panel 国将举办名为数字游戏的年度表演.每个省派出一名选手. 国家有 n 个编号从 1 到 n 的省,每个省刚好有一条路径将其与其他省相连 ...

  2. Codeforces 980 E. The Number Games

    \(>Codeforces \space 980 E. The Number Games<\) 题目大意 : 有一棵点数为 \(n\) 的数,第 \(i\) 个点的点权是 \(2^i\) ...

  3. Codeforces 980E The Number Games 贪心 倍增表

    原文链接https://www.cnblogs.com/zhouzhendong/p/9074226.html 题目传送门 - Codeforces 980E 题意 $\rm Codeforces$ ...

  4. codeforces 980E The Number Games

    题意: 给出一棵树,要求去掉k个点,使得剩下的还是一棵树,并且要求Σ(2^i)最大,i是剩下的节点的编号. 思路: 要使得剩下的点的2的幂的和最大,那么肯定要保住大的点,这是贪心. 考虑去掉哪些点的话 ...

  5. Codeforces 980E The Number Games - 贪心 - 树状数组

    题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗有$n$个点的树,$i$号点的权值是$2^{i}$要求删去$k$个点,使得剩下的点仍然连通,并且总权值和最大,问删去的所有点的编号. ...

  6. Codeforces Round #480 (Div. 2) E - The Number Games

    题目大意:给你n个点的一棵树, 每个点的权值为2^i ,让你删掉k个点使得剩下的权值和最大. 思路:这题还是比较好想的, 我们反过来考虑, 剩下一个的情况肯定是选第n个点,剩下两个 我们肯定优先考虑第 ...

  7. The Number Games CodeForces - 980E (树, 贪心)

    链接 大意: 给定$n$节点树, 求删除$k$个节点, 使得删除后还为树, 且剩余点$\sum{2^i}$尽量大 维护一个集合$S$, 每次尽量添加最大的点即可 这样的话需要支持求点到集合的最短距离, ...

  8. cf round 480E The Number Games

    题意:给一棵树,点$i$的点权是$2^i$,你需要删掉$k$个点,使得剩下的点连通的情况下剩下的点权值和最大. $k \leq n \leq 10^6$ 如果考虑删哪些点,是不好考虑的,会出问题. 反 ...

  9. POJ1336 The K-League[最大流 公平分配问题]

    The K-League Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 715   Accepted: 251 Descri ...

随机推荐

  1. Android Studio NDK JNI动态注册本地方法

    概述 可能大家觉得javah生成的函数名又臭又长,不太好看.这里可以提供另外一种方法来动态注册c++函数,让其根Java中的native方法关联起来. 实现 这里通过JNIEnv的Resisterna ...

  2. 微信小程序-全国快递查询

    微信小程序-全国快递查询 摘要:WeChat.小程序.JS 开发过程 源码下载 1. GitHub 2. 百度云 链接:https://pan.baidu.com/s/1XVbtT2JsZslg4Y0 ...

  3. session,cookie,sessionStorage,localStorage的区别

    浏览器的缓存机制提供了可以将用户数据存储在客户端上的方式,可以利用cookie,session等跟服务端进行数据交互. 一.cookie和session cookie和session都是用来跟踪浏览器 ...

  4. Scrapy 解决Scrapy安装时报错"Microsoft Visual C++ 14.0 is required"

    问题描述 当前环境win10,python_3.6.1,64位.在windows下,在dos中运行pip install Scrapy报错:error: Microsoft Visual C++ 14 ...

  5. Android 官方DEMO BasicNetworking

    本示例演示如何使用Android API检查网络连接. Demo下载地址:https://github.com/googlesamples/android-BasicNetworking/#readm ...

  6. jdk1.8新特性总结

    一.引言 jdk1.8出来已经一段时间了,现在1.9也已经出来了,但是很多公司(我们公司也一样)不太愿意升级到高版本的jdk,主要是有老的项目要维护,还有升级的话配套的框架也要升级,要考虑的细节事情太 ...

  7. H5——简易马祖

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  8. java使用插件pagehelper在mybatis中实现分页查询

    摘要: com.github.pagehelper.PageHelper是一款好用的开源免费的Mybatis第三方物理分页插件 PageHelper是国内牛人的一个开源项目,有兴趣的可以去看源码,都有 ...

  9. 自动化测试基础篇--Selenium单选框(Radio)复选框(CheckBox)

    摘自:https://www.cnblogs.com/sanzangTst/p/7686602.html 一.什么是单选框.复选框? 二.单选框:radio 三.复选框:checkbox 四.判断是否 ...

  10. SQL Server 锁实验(INSERT加锁探究)

    insert语句: 其上锁情况为: insert语句会对表上的所有索引作出更新,因此这里看到的索引列较多,我们先把所有的索引搞出来看看: 可以看到所有索引都涉及到了,然后我们来仔细分析下加锁情况: 1 ...