首页 > 其他分享 >DYN / 消防局的设立 / Spread of Information / 将军令 题解

DYN / 消防局的设立 / Spread of Information / 将军令 题解

时间:2024-10-27 16:42:37浏览次数:1  
标签:Information limits min int 题解 tot leq now 将军令

前言

四倍经验:[POI2011] DYN-Dynamite[HNOI2003] 消防局的设立[ARC116E] Spread of Information将军令

题意简述

给你一棵 \(n\) 个结点的树和点集 \(S\),你要选出 \(k\) 个关键点 \(T\),求 \(\min \max \limits _ {u \in S} \min \limits _ {v \in T} \operatorname{dis}(u, v)\)。

\(1 \leq k \lt n \leq 3 \times 10^5\)。

题目分析

最大值最小?一眼二分。考虑 check(x) 表示是否存在一种 \(T\),满足 \(\max \limits _ {u \in S} \min \limits _ {v \in T} \operatorname{dis}(u, v) \leq x\)。

那么转变成了对于 \(u \in S\),要求距离其 \(x\) 内存在一个 \(v \in T\)。我们求出满足条件的 \(\min |T|\),与 \(k\) 作比较,若 \(\min |T| \leq k\) 说明存在这样的 \(T\)。

考虑贪心。从叶子向上考虑,当前点能不放就不放入 \(T\)。正确性是显然的,想要证明可以把最优答案的点向下移动来证明,读者自证不难。

我们考虑记 \(f_u\) 表示 \(u\) 子树里最远不合法的 \(v \in S\) 距离 \(u\) 的距离。向上转移、统计答案是简单的。但是,不要忘记了,有可能子树间可会互相影响。所以我们再记 \(g_u\) 表示 \(u\) 子树里最近的 \(v \in T\) 距离 \(u\) 的距离,转移同样简单。

如果 \(f_u = x\),说明必须选择 \(u\),即 \(T \gets T \cup \{u\}\),\(f_u = -\infty\),\(g_u = 0\);

否则如果 \(f_u + g_u \leq x\),说明子树间可以互相解决,所以 \(f_u \gets 0\)。

不要忘记,如果根的 \(f \neq -\infty\),需要额外一个点。

代码

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

const int N = 300010;

int n, m;
bool have[N];
vector<int> edge[N];

int tot = 0, f[N], g[N];

void dfs(int now, int fa, int x) {
	f[now] = have[now] ? 0 : -0x3f3f3f3f;
	g[now] = 0x3f3f3f3f;
	for (const auto& to: edge[now]) if (to != fa) {
		dfs(to, now, x);
		f[now] = max(f[now], f[to] + 1);
		g[now] = min(g[now], g[to] + 1);
	}
	if (f[now] == x) {
		++tot;
		f[now] = -0x3f3f3f3f;
		g[now] = 0;
	} else if (f[now] + g[now] <= x) {
		f[now] = -0x3f3f3f3f;
	}
}

bool check(int x) {
	tot = 0, dfs(1, 0, x);
	if (f[1] >= 0) ++tot;
	return tot <= m;
}

signed main() {
	scanf("%d%d", &n, &m);
	for (int i = 1, x; i <= n; ++i) scanf("%d", &x), have[i] = x;
	for (int i = 1, u, v; i <= n - 1; ++i) {
		scanf("%d%d", &u, &v);
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	int l = 0, r = n, mid, ans = 0;
	while (l <= r) {
		mid = (l + r) >> 1;
		if (check(mid)) ans = mid, r = mid - 1;
		else l = mid + 1;
	}
	printf("%d", ans);
	return 0;
}

标签:Information,limits,min,int,题解,tot,leq,now,将军令
From: https://www.cnblogs.com/XuYueming/p/18508482

相关文章

  • CSP-J 2024 复赛题解
    T1数据仅有52,极小的数据范围导致这题只有一个问题:如何简短方便的去重并统计。我选择了map做法:每个输入查找map中之前是否记录过此元素,如果记录过则证明已经拥有这张牌,反之则记录并将统计数增加。代码如下:#include<bits/stdc++.h>usingnamespacestd;intn;map<stri......
  • Stema练习题:十四届蓝桥杯STEMA考试Python真题试卷题解
    来源:十四届蓝桥杯STEMA考试Python真题试卷第一套编程第四题这个程序虽然代码量不大,但综合运用了多种基础算法和数据结构:贪心策略选择窗口、模拟现实过程、线性查找最小值、效率高(时间复杂度为O(N)O(N)O(N))。题目描述:编程实现:某服务大厅同时开放3个窗口为客户办理......
  • Codeforces Round 982 div2 个人题解(A~D2)
    CodeforcesRound982div2个人题解(A~D2)Dashboard-CodeforcesRound982(Div.2)-Codeforces火车头#define_CRT_SECURE_NO_WARNINGS1#include<algorithm>#include<array>#include<bitset>#include<cmath>#include<cstdio>#in......
  • CF102354B Yet Another Convolution 题解
    题目描述给定长为\(n\)的数列\(a,b\),求数列\(c\)满足:\[c_k=\max_{\gcd(i,j)=k}|a_i-b_j|\\\]数据范围\(1\len\le10^5,1\lea_i,b_i\le10^9\)。时间限制\(\texttt{6s}\),空间限制\(\texttt{256MB}\)。分析别被题目名字带偏了,这道题跟卷积没有一点关系。如果......
  • 洛谷 P5738 【深基7.例4】歌唱比赛 C语言 题解
    题目描述n(n≤100)n(n≤100) 名同学参加歌唱比赛,并接受 m(m≤20)m(m≤20) 名评委的评分,评分范围是 00 到 1010 分。这名同学的得分就是这些评委给分中去掉一个最高分,去掉一个最低分,剩下 m−2m−2 个评分的平均数。请问得分最高的同学分数是多少?评分保留 22 位小数......
  • CSP-J 2024第二轮试题解析
    2024年10月26日,CSP-J/S2024第二轮认证圆满结束;这次入门组的比赛重点考察了模拟和动态规划算法,还涉及到字符串、贪心、前缀和等内容的考察,相比去年来说,对思维能力的考察更多。前两题比去年好做,第三题的部分分也比较好拿,但是第四题的难度明显比去年高,预计分数线会出现小幅提升。......
  • 如何利用递归和迭代构建二叉树?详解题解
    文章目录根据二叉树创建字符串思路代码二叉树的层序遍历思路代码二叉树的最近公共祖先思路代码二叉搜索树与双向链表思路代码从前序与中序遍历序列构造二叉树思路代码总结根据二叉树创建字符串题目:样例:可以看见,唯一特殊的就是左子树,当右子树存在的时候左......
  • 2024CSP-J题解附源码T1-T3
    T1#include<bits/stdc++.h>usingnamespacestd;///T1题解///输入行数n///输入n行,每行一个字符串,字符串只有两个字母组成,第一个字母是花色,第二个字母是点数。///一副牌只有52种组合,因为map能去重,所以用map进行统计不同组合数即mp.size()///结果为52-mp.size()map<string......
  • CF771A. Bear and Friendship Condition 题解 并查集
    题目链接:https://codeforces.com/problemset/problem/771/A视频讲解:https://www.bilibili.com/video/BV1tZ1FYPELp/?p=6题目大意:判断一个无向图中的每个连通块是否都是一个完全图。首先我们可以用并查集维护每个连通块的大小。其次,我们可以开一个\(cnt_i\)表示以节点\(i\)......
  • Codeforces Round 981 (Div. 3) 10.24 (ABCDE)题解
    CodeforcesRound981(Div.3)2024.10.24题解A.SakurakoandKosuke题意:\(Sakurako\)与\(Kosuke\)正在玩游戏,一个点在原点\(x=0\)的起始位置。对于第\(i\)次操作,点会移动\(2\asti-1\)步。两人轮流操作,Sakurako先手,每次将点往负方向移动;Kosuke每次将点往正方向移动......