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 ...
随机推荐
- css3 简易时钟
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- es6 语法 (数值扩展)
{ //二进制数值都是0b开头,八进制0o console.log(0b111110111) console.log(0o767); } { console.log('15',Number.isFin ...
- POJ 2942Knights of the Round Table(tarjan求点双+二分图染色)
Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 13954 Accepted: 4673 Description Bein ...
- WPF控件库:文字按钮的封装
需求:封装按钮,按钮上面只显示文字.在鼠标移上去.鼠标点击按钮.以及将按钮设为不可用时按钮的背景色和前景色需要发生变化 实现:继承Button类,封装如下6个属性: #region 依赖属性 /// ...
- (网页)table加上分页,优点可随便加样式
1.先有静态的页面: <div class="col-xs-12"> <table id="tbtablesaleinfo" class=&q ...
- codeforces 632C The Smallest String Concatenation
The Smallest String Concatenation 题目链接:http://codeforces.com/problemset/problem/632/C ——每天在线,欢迎留言谈论. ...
- 原型模式ProtoType
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2019/3/4 21:49 # @Author : ChenAdong # @emai ...
- CentOS7中启动Tomcat后,8080端口不能被外部访问的解决办法。
运行:/sbin/iptables -I INPUT -p tcp --dport 8080 -j ACCEPT
- Mybatis 学习---${ }与#{ }获取输入参数的区别、Foreach的用法
一.Mybatis中用#{}和${}获取输入参数的区别 1.“#{}“和“${}”都可以从接口输入中的map对象或者pojo对象中获取输入的参数值.例如 <mapper namespace=&q ...
- 两个Map的对比,三种方法,将对比结果写入文件。
三种方法的思维都是遍历一个map的Key,然后2个Map分别取这2个Key值所得到的Value. #第一种用entry private void compareMap(Map<String, S ...