首页 > 其他分享 >CodeForces 1266F Almost Same Distance

CodeForces 1266F Almost Same Distance

时间:2024-01-15 18:45:14浏览次数:49  
标签:typedef fa Almost CodeForces long int maxn ans 1266F

洛谷传送门

CF 传送门

好厉害。

特判 \(k = 1\)。首先经过观察,我们可以按照 \(k\) 的奇偶性讨论:

  1. \(k\) 为偶数,有一个中心点挂了若干条长度为 \(\frac{k}{2}\) 的链。
  2. \(k\) 为偶数,有两个中心点,两边挂了若干条长度为 \(\frac{k}{2}\) 的链;
  3. \(k\) 为奇数,有一个中心点挂了若干条长度为 \(\frac{k + 1}{2}\) 的链和至多一条长度为 \(\frac{k - 1}{2}\) 的链。

根据上面我们有 \(ans_k \ge ans_{k + 2}\)。最后取个后缀 \(\min\) 即可。接下来考虑如何处理这 \(3\) 种贡献。

我们可以把每个点的每棵子树挂的最长链预处理出来。然后按照这个长度扫描线。设当前点 \(u\) 出现次数为 \(b_u\)。

对于第一种贡献,可以直接让 \(ans_{2i} \gets b_u\)。

对于第二种贡献,我们要讨论 \(u\) 的所有邻居。维护 \(c_u\) 表示 \(u\) 的所有儿子的 \(b_u\) 的最大值。然后让 \(ans_{2i} \gets \max(b_u + c_u - 2, b_u + b_{fa_u} - 2)\) 即可。\(-2\) 是因为两棵子树互相重复贡献了。

对于第三种贡献,若 \(u\) 是在长度 \(i\) 中第一次出现,有 \(ans_{2i + 1} \gets b_u\),否则 \(ans_{2i - 1} \gets b_u\)。

时间复杂度 \(O(n)\)。

code
// Problem: F. Almost Same Distance
// Contest: Codeforces - Codeforces Global Round 6
// URL: https://codeforces.com/contest/1266/problem/F
// Memory Limit: 256 MB
// Time Limit: 5000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

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

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

const int maxn = 1000100;

int n, f[maxn], g[maxn], h[maxn], a[maxn], b[maxn], c[maxn], fa[maxn];
bool vis[maxn];
vector<int> G[maxn], vc[maxn];

void dfs(int u, int fa) {
	for (int v : G[u]) {
		if (v == fa) {
			continue;
		}
		::fa[v] = u;
		dfs(v, u);
		vc[f[v] + 1].pb(u);
		if (f[v] + 1 > f[u]) {
			g[u] = f[u];
			f[u] = f[v] + 1;
		} else if (f[v] + 1 > g[u]) {
			g[u] = f[v] + 1;
		}
	}
}

void dfs2(int u, int fa) {
	for (int v : G[u]) {
		if (v == fa) {
			continue;
		}
		h[v] = max(h[u] + 1, f[v] + 1 == f[u] ? g[u] + 1 : f[u] + 1);
		vc[h[v]].pb(v);
		dfs2(v, u);
	}
}

void solve() {
	scanf("%d", &n);
	for (int i = 1, u, v; i < n; ++i) {
		scanf("%d%d", &u, &v);
		G[u].pb(v);
		G[v].pb(u);
	}
	for (int i = 1; i <= n; ++i) {
		a[1] = max(a[1], (int)G[i].size() + 1);
	}
	dfs(1, -1);
	dfs2(1, -1);
	for (int i = n; i; --i) {
		for (int u : vc[i]) {
			++b[u];
			c[fa[u]] = max(c[fa[u]], b[u]);
			a[i * 2] = max({a[i * 2], b[u] + b[fa[u]] - 2, b[u] + c[u] - 2, b[u]});
			if (!vis[u]) {
				a[i * 2 + 1] = max(a[i * 2 + 1], b[u]);
			}
			a[i * 2 - 1] = max(a[i * 2 - 1], b[u]);
			vis[u] = 1;
		}
		for (int u : vc[i]) {
			vis[u] = 0;
		}
	}
	for (int i = n; i; --i) {
		a[i] = max({a[i], a[i + 2], 1});
	}
	for (int i = 1; i <= n; ++i) {
		printf("%d ", a[i]);
	}
}

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

标签:typedef,fa,Almost,CodeForces,long,int,maxn,ans,1266F
From: https://www.cnblogs.com/zltzlt-blog/p/17966026

相关文章

  • hey_left 2 Codeforces Round 918 (Div. 4) 续
    题目链接F.常规的树状数组求逆序对需要注意的是,因为是下标与值的映射,所以数值不能为负数,也不能太大然后传参数的时候,参数是最大数值切记切记#include<bits/stdc++.h>usingnamespacestd;constintN=2e5+10;template<typenameT>structTreeArray{vector<T>t......
  • Codeforces Round 919 (Div. 2)(A~D) 题解
    CodeforcesRound919(Div.2)(A~D)题解A.SatisfyingConstraints题意:给你一些条件让你求出满足条件的整数有多少个。模拟即可。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constllMAXN=2e5+5;llTex=1,n;voidAC(){ cin>>n; lll=......
  • Codeforces Round 919 (Div. 2)
    CodeforcesRound919(Div.2)A-SatisfyingConstraints#include<bits/stdc++.h>#defineendl'\n'#defineintlonglongusingnamespacestd;constintN=1e6+10;voidsolve(){ intn; intl=-1; intr=1e9+10; cin>>......
  • CodeForces 1920F2 Smooth Sailing (Hard Version)
    洛谷传送门CF传送门首先需要知道的一个trick:判断一个点是否在一个闭合回路内部,从这个点向任意方向引一条射线,若不考虑相切,那么和回路的交点为奇数时这个点在回路内部,否则在外部。那么这题要判断一个回路是否包含全部的island,可以找到任意一个island向右引一条射线。给每......
  • Hey left 1 Codeforces Round 918 (Div. 4)
    题目链接A.3个数,其中2个数相同,输出不相同的那个可以用ifelse判断,较为麻烦用的map,输出出现一次的#include<bits/stdc++.h>usingnamespacestd;constintN=1e5+10;voidsolve(){map<int,int>mp;for(inti=0,x;i<3;i++){cin>>x;mp[x]++;......
  • CodeForces 1237H Balanced Reversals
    洛谷传送门CF传送门容易想到把\(s,t\)分成长度为\(2\)的段考虑。容易发现\(00,11\)的个数在操作过程中不会改变,所以若两串的\(00\)或\(11\)个数不相等则无解。考虑依次对\(i=2,4,\ldots,n\)构造\(s[1:i]=t[n-i+1:n]\)。对于\(s_{j-1}s_j=y......
  • Codeforces [Hello 2024]
    CodeforcesHello2024主打一个昏了头A.WalletExchange#include<bits/stdc++.h>#defineendl'\n'//#defineintlonglongusingnamespacestd;constintN=2e5+10;inta,b;voidsolve(){ cin>>a>>b; if((a+b)&1)cout<<......
  • CodeForces 1379E Inverse Genealogy
    洛谷传送门CF传送门\(n\)为偶数显然无解。否则我们可以构造一棵\(n\)个点的完全二叉树,当\(n+1\)是\(2\)的幂时满足\(m=1\),否则\(m=0\)。当\(n\ge5\)时可以递归至\((n-2,m-1)\),再挂一个叶子即可。但是可能会出现\(n+1\)不是\(2\)的幂,但\(n-......
  • codeforces比赛(3):codeforces good_bye_2023
    A、2023跳转原题点击此:A题地址1、题目大意  在一个乘积可能等于2023的数组a中去掉了k个数,得到新的长度为n的b数列。请你输出k个数,使得这k个数与b数列相乘为2023.如果不存在则输出No。2、题目解析  因为这道题的n和k都是不超过5,所以我们只需要算出b数组的乘积是否是2023的......
  • Codeforces Round 918 (Div. 4) (前缀和,权值树状数组,二维偏序, python + golang)
    Dashboard-CodeforcesRound918(Div.4)-Codeforces  fromcollectionsimport*defsolve():a,b,c=list(map(int,input().split()))hs=defaultdict(int)hs[a]+=1hs[b]+=1hs[c]+=1foriinhs:ifhs[i]=......