Codeforces Global Round 6 F

https://codeforces.com/contest/1266/problem/F

特判一些极端如almost-1和集合中仅存两点的情况

大致分两种情况

最终集于某一点或两点

这些点分立不同子树

那么处理每个点为根不同子树的最远距离

显然的,若最远距离为d,可选取[1,d]的距离

1.一点

又可分为

A.1条长度为k,s条长度为k+1的

s+1更新ans[2k+1]

B.s条长度为k的

s更新ans[2k]和ans[2k-1]

2.两点

s1条长度为k的到u点

s2条长度为k的到v点

s1+s2更新 ans[2k]

#include<bits/stdc++.h>
#define file(KSCN) freopen(KSCN".in","r",stdin),freopen(KSCN".out","w",stdout)
using namespace std;
typedef long long ll;
namespace IO{
	const int ios=1<<17;
	char R[ios],*Rc=R,*RB=R;int pass;
	inline int gec(){return(Rc==RB&&(RB=(Rc=R)+fread(R,1,ios,stdin),Rc==RB))?EOF:*Rc++;}
	template<typename Tp>inline int read(Tp&A){
		static int c,sg;c=gec();sg=0;A=0;
		while(!isdigit(c)&&c!=EOF)sg|=(c=='-'),c=gec();
			if(c==EOF)return EOF;
		while(isdigit(c))A=(A<<3)+(A<<1)+(c^'0'),c=gec();
		return A=sg?-A:A,0;
	}
	inline int read(){return read(pass),pass;}
}
using IO::gec;using IO::read;
const int N=5e6+5;
template<typename T>void cmax(T&a,T b){if(b>a)a=b;}
typedef pair<int,int> par;
vector<int>e[N];
vector< par >a[N];
int du[N],up[N],res[N];
int n;
void DFS1(int x,int FAQ){
	for(int to:e[x])if(to!=FAQ)
		DFS1(to,x),cmax(du[x],du[to]+1);
}
void DFS2(int x,int upon){
	par b[2];
	b[0]=make_pair(up[x]=(upon+1),-1);
	b[1]=make_pair(-1,-1);
	for(int to:e[x])if(du[to]<du[x]){
		par su=make_pair(du[to]+1,to);
		for(int k=0;k<2;k++)
			if(su>b[k])swap(su,b[k]); 
	}
	for(int to:e[x])if(du[to]<du[x])
		DFS2(to,b[b[0].second==to].first);
}
int main(){
	read(n);
	for(int i=1,u,v;i<n;i++){
		read(u);read(v);--u;--v;
		e[u].push_back(v);
		e[v].push_back(u);
	} 
	DFS1(0,-1);
	DFS2(0,-1);
	vector<int>cur;
	for(int x=0;x<n;x++){
		cur.clear();
		if(up[x])cur.push_back(up[x]);
		for(int to:e[x])if(du[to]<du[x])
			cur.push_back(du[to]+1);
		sort(cur.begin(),cur.end());
		for(int dd:cur)if(a[x].empty()||a[x].back().first!=dd)
			a[x].push_back(make_pair(dd,1));
		else a[x].back().second++;
	}
	for(int i=1;i<=n;i++)res[i]=1;
	int diam=0;
	for(int x=0;x<n;x++)cmax(diam,a[x].back().first);
	for(int i=1;i<=diam;i++)res[i]=2;
	for(int x=0;x<n;x++)cmax(res[1],(int)e[x].size()+1); 
	for(int x=0;x<n;x++){
		int sum=e[x].size();
		for(int i=0,ios=a[x].size();i<ios;i++){
			cmax(res[(a[x][i].first<<1)-1],sum);
			if(i>0)cmax(res[(a[x][i-1].first<<1)+1],sum+1);//>=i & single (i-1)
			cmax(res[(a[x][i].first<<1)],sum);
			sum-=a[x][i].second;
		}
	}
	for(int x=0;x<n;x++){
		for(int to:e[x])if(du[to]<du[x]){
			int sum=e[x].size()+e[to].size()-2,c1=0,c2=0;
			for(auto QwQ:a[x])if(QwQ.first==du[to]+1)QwQ.second--;
			for(auto QwQ:a[to])if(QwQ.first==up[to])QwQ.second--;
			while(c1<a[x].size()&&c2<a[to].size()){
				int t=min(a[x][c1].first,a[to][c2].first);
				cmax(res[t<<1],sum);
				if(t==a[x][c1].first)sum-=a[x][c1++].second;
				if(t==a[to][c2].first)sum-=a[to][c2++].second;
			}
			for(auto QwQ:a[x])if(QwQ.first==du[to]+1)QwQ.second++;
			for(auto QwQ:a[to])if(QwQ.first==up[to])QwQ.second++;
		}
	}
	for(int i=n-2;i>=1;i--)cmax(res[i],res[i+2]);
	for(int i=1;i<=n;i++)printf("%d ",res[i]);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值