首页 > 其他分享 >AtCoder Grand Contest 008 F Black Radius

AtCoder Grand Contest 008 F Black Radius

时间:2023-03-23 13:12:16浏览次数:50  
标签:AtCoder val Contest int min long maxn Black

洛谷传送门

AtCoder 传送门

神题!!!!111

考虑如何不重不漏地计数。先考虑全为 1 的情况,令 \(f(u,d)\) 为与 \(u\) 的距离 \(\le d\) 的点集。

首先单独算全集,那么对于不是全集的集合就会有一些比较好的性质。

考虑若有若干个 \(f(u,d)\) 同构,那 只在 \(d\) 最小的时候计数

那么 \(f(u,d)\) 需要满足不能覆盖全集,且不存在与 \(u\) 相邻的点 \(v\),使得 \(f(u,d) = f(v,d-1)\)(由于 \(d\) 最小的约束)。

考虑若存在后者时发生了什么。把 \(v\) 这棵子树抠掉之后,剩下的点与 \(u\) 距离 \(\le d - 2\)。

令 \(f_u\) 为以 \(u\) 为根的子树最大深度,\(g_u\) 为以 \(u\) 为根的子树次大深度(不存在则为 \(0\)),\(d_u\) 为 \(f(u,d)\) 最大能取到的 \(d\),则等价于 \(d_u < \min(f_u,g_u+2)\)。

换根求出 \(f_u,g_u\) 即可。于是我们就做完了全为 1 的情况。

现在有一些点是 0。但是我们发现不能完全不考虑它们,因为我们发现有些 1 点的 \(d_u\) 上界过于严苛导致有些情况没有考虑到,那我们将这些情况放到 0 点计算。

发现 0 点的上界仍然可以取到,但是下界并非 \(0\)。设任意 0 点为 \(u\),则未算到的情况满足 1 点所在子树中全被覆盖,并且还可能覆盖了别的子树。设 \(h_u\) 为以 \(u\) 为根的存在 1 点的子树的最大深度,则对于 0 点,\(h_u \le d_u < \min(f_u,g_u+2)\)。

此时的 \(h_u\) 仍然可以换根求出,于是我们就以 \(O(n)\) 的时空复杂度做完了。

code
// Problem: F - Black Radius
// Contest: AtCoder - AtCoder Grand Contest 008
// URL: https://atcoder.jp/contests/agc008/tasks/agc008_f
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 200100;
const int inf = 0x3f3f3f3f;

int n, head[maxn], len, a[maxn], sz[maxn], f[maxn], g[maxn], h[maxn];
ll ans = 1;

struct edge {
	int to, next;
} edges[maxn << 1];

void add_edge(int u, int v) {
	edges[++len].to = v;
	edges[len].next = head[u];
	head[u] = len;
}

void dfs(int u, int fa) {
	if (a[u]) {
		sz[u] = 1;
	} else {
		h[u] = inf;
	}
	for (int i = head[u]; i; i = edges[i].next) {
		int v = edges[i].to;
		if (v == fa) {
			continue;
		}
		dfs(v, u);
		sz[u] += sz[v];
		int val = f[v] + 1;
		if (val > f[u]) {
			g[u] = f[u];
			f[u] = val;
		} else if (val > g[u]) {
			g[u] = val;
		}
		if (sz[v]) {
			h[u] = min(h[u], f[v] + 1);
		}
	}
}

void dfs2(int u, int fa) {
	ans += max(0, min(f[u], g[u] + 2) - h[u]);
	for (int i = head[u]; i; i = edges[i].next) {
		int v = edges[i].to;
		if (v == fa) {
			continue;
		}
		int val = (f[u] == f[v] + 1) ? g[u] + 1 : f[u] + 1;
		if (val > f[v]) {
			g[v] = f[v];
			f[v] = val;
		} else if (val > g[v]) {
			g[v] = val;
		}
		if (sz[v] != sz[1]) {
			h[v] = min(h[v], val);
		}
		dfs2(v, u);
	}
}

void solve() {
	scanf("%d", &n);
	for (int i = 1, u, v; i < n; ++i) {
		scanf("%d%d", &u, &v);
		add_edge(u, v);
		add_edge(v, u);
	}
	for (int i = 1; i <= n; ++i) {
		scanf("%1d", &a[i]);
	}
	dfs(1, -1);
	dfs2(1, -1);
	printf("%lld\n", ans);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:AtCoder,val,Contest,int,min,long,maxn,Black
From: https://www.cnblogs.com/zltzlt-blog/p/17247068.html

相关文章

  • [HMV] Blackhat
    0x00配置攻击机IP:172.16.1.25靶机IP:172.16.1.1230x01攻击使用Nmap扫描目标靶机开放的端口┌──(root㉿Kali-VM)-[~]└─#nmap-sC-sV-p-172.16.1.123......
  • AtCoder Beginner Contest 246
    AtCoderBeginnerContest246D题意求一个\(x\geqn\)使得\(x=a^3+a^2b+ab^2+b^3\)且\(n\leq10^{18}\)思路变形\(x=(a+b)(a^2+b^2)\),那么a、b的范围在1e6从大到小......
  • SMU Spring 2023 Trial Contest Round 1(6/8)
    SMUSpring2023TrialContestRound1(6/8)A.PrependandAppendPrependandAppend只需考虑给定字符串两端是否符合10或01即可,双指针从两端模拟即可。#include<iost......
  • AtCoder Beginner Contest 141
    AtCoderBeginnerContest141D-PowerfulDiscountTickets贪心+堆#include<bits/stdc++.h>#definelllonglongusingnamespacestd;constintN=1e5+5;......
  • [AtCoder] B - Counting Grids
      Thekeyobservationisthatthereisalwaysatmost1cellthatviolatesbothconditions. Proof: ifxviolatesbothconditions,thatmeansallothe......
  • SMU Spring 2023 Trial Contest Round 1
    A.PrependandAppend如果两段字符不同就可以删掉,如果不能删了就是最初的字符串#include<bits/stdc++.h>usingnamespacestd;voidsolve(){intn;stri......
  • AtCoder Beginner Contest 294
    题解报告基本的一些理解和问题都在注释中A:Filter//水题#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>usingnamespacestd;intm......
  • [??记录] AtCoder 练习
    3.19arc066_c(dp,观察)观察:只会在负号右边添加\((/)\)两个位置之间至多一个括号。括号不会嵌套多层。\(f[i][j]\)表示处理完\(i\)个数,有\(j\)个未匹配左括号......
  • AtCoder Beginner Contest 294
    A-Filter(abc294a)题目大意给定一个数组,不改变原顺序,输出是偶数的数。解题思路模拟即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL......
  • AtCoder Beginner Contest 293
    A-SwapOddandEven#include<bits/stdc++.h>usingnamespacestd;int32_tmain(){ strings; cin>>s; for(inti=0;i+1<s.size();i+=2) swap(......