首页 > 其他分享 >LibreOJ #6042. 「雅礼集训 2017 Day7」跳蚤王国的宰相

LibreOJ #6042. 「雅礼集训 2017 Day7」跳蚤王国的宰相

时间:2022-11-15 16:15:32浏览次数:50  
标签:ch 重心 LibreOJ int Day7 mid 6042 maxn size

题意

修改一条边意味着,删掉一条边,并加入一条新的边。

给出一棵树,对于每个点,求出使它变成重心的最小修改边数。

分析

先找到重心,对于不是重心的一个点 \(i\), 有两种方法,一是将重心的前几个大的子树接在 \(i\) 下面(当然不包括 \(i\) 属于的子树),二是将重心和其余子树一起接到 \(i\) 下面,再不断割 重心的前几个大的子树 ,使得 重心 在以 \(i\) 为根的 size 小于等于 \(n/2\) 。为什么呢?源于重心的定义。这样可以先求出重心,在将子树 sort 一下,求前缀和,再二分需要割的子树数量,就是答案了。

\(code\)

#include<bits/stdc++.h>
#define N 1000005
using namespace std;
int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f; 
} 
void write(int x){
	if(x>9) write(x/10);
	putchar(x%10+'0');
}
int n,tot,root,maxpart=1e9,cnt;
int Head[N],to[N<<1],Next[N<<1];
int size[N],c[N],sum[N],pos[N],vv[N];
struct node{
	int id,val;
	bool operator < (const node& A)const{return val>A.val;}
}son[N];
void add(int u,int v){
	to[++tot]=v,Next[tot]=Head[u],Head[u]=tot;
}
void dfs1(int x,int fa){
	size[x]=1;int maxn=0;
	for(int i=Head[x];i;i=Next[i]){
		int y=to[i];if(y==fa) continue;
		dfs1(y,x);size[x]+=size[y];
		maxn=max(maxn,size[y]);
	}
	maxn=max(maxn,n-size[x]);
	if(maxn<maxpart) maxpart=maxn,root=x;
}
void dfs(int x,int fa,int gp){
	size[x]=1,c[x]=gp;
	for(int i=Head[x];i;i=Next[i]){
		int y=to[i];if(y==fa) continue;
		dfs(y,x,gp);size[x]+=size[y];
	}
}
void dfs2(int x,int fa){
	size[x]=1;
	for(int i=Head[x];i;i=Next[i]){
		int y=to[i];if(y==fa) continue;
		dfs(y,x,y);size[x]+=size[y];
		son[++cnt].id=y,son[cnt].val=size[y];
	}
} 
int main(){
//	freopen("diortnec.in","r",stdin);
//	freopen("diortnec.out","w",stdout);
	n=read();
	for(int i=1;i<n;++i){
		int u=read(),v=read();
		add(u,v),add(v,u);
	}
	dfs1(1,0);
	dfs2(root,0); 
	sort(son+1,son+1+cnt);
	for(int i=1;i<=cnt;++i) sum[i]=sum[i-1]+son[i].val,pos[son[i].id]=i,vv[son[i].id]=son[i].val;
	for(int i=1;i<=n;++i){
		if(i==root){printf("0\n");continue;}
		int l=0,r=cnt,ans1=0,ans2=0;
		while(l<=r){
			int mid=(l+r)>>1;
			int val=sum[mid],flag=0;
			if(pos[c[i]]<=mid) val-=vv[c[i]],flag=1;
			if(size[c[i]]+val>=(n+1)/2) ans1=mid-flag,r=mid-1;
			else l=mid+1;
		} 
		l=0,r=cnt;
		while(l<=r){
			int mid=(l+r)>>1;
			int val=sum[mid],flag=0;
			if(pos[c[i]]<=mid) val-=vv[c[i]],flag=1;
			if(size[i]+val>=(n+1)/2) ans2=mid-flag,r=mid-1;
			else l=mid+1;
		} 
		write(min(ans1+1,ans2)),puts("");
	}
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}

标签:ch,重心,LibreOJ,int,Day7,mid,6042,maxn,size
From: https://www.cnblogs.com/jiangchenyyds/p/16892722.html

相关文章

  • 牛客java选择题每日打卡Day7
    牛客java选择题每日打卡Day7......
  • LeetCode刷题记录.Day7
    有效的字母异位词题目链接242.有效的字母异位词-力扣(LeetCode)classSolution{public:boolisAnagram(strings,stringt){intrecord[26]={0};......
  • day7
    [0707.设计链表]classMyLinkedNode{intval;MyLinkedNodenext;publicMyLinkedNode(intval,MyLinkedNodenext){val=this.val;......
  • 【leetcode_C++_字符串_day7】344_反转字符串&541_反转字符串II&&剑指Offer_05_替换空
    344.反转字符串编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用O(1)......
  • 学习python-Day79
    昨日内容回顾前端发展历史vue react谷歌flutter,Dart语言uni-app:小公司vue:3.x2.x3.x====>ts2.x====>jsvue渐进式MVVMM层:model,数据层,jsV层:view,视......
  • 学习python-Day77
    今日学习内容一、⽬录结构说明1.⽬录结构发展过程一块盘:根目录二块盘:/usr目录继续扩展>>>:FHS文件系统目录规范2.重要目录数据信息说明网卡配置文件 /etc/sysc......
  • 【算法训练营day7】LeetCode454. 四数相加II LeetCode383. 赎金信 LeetCode15. 三数之
    【算法训练营day7】LeetCode454.四数相加IILeetCode383.赎金信LeetCode15.三数之和LeetCode18.四数之和LeetCode454.四数相加II题目链接:454.四数相加II初次尝......
  • 学习python-Day76
    今日学习内容一、虚拟机关键配置名词解释1.虚拟网络编辑器说明桥接模式​ 配置的地址信息和物理主机地址信息相同,容易造成地址冲突NAT模式​ 配置的地址信息和物......
  • 学习python-Day75
    运维的本质运维:运行维护应用程序岗位需求:自动化运维、DBA、docker+K8s...运维职责:尽可能保证应用程序24小时不间断运行尽可能保证数据的安全尽可能提升程序的......
  • 22 暑期C班 Day7—附加赛
    线段树什么的最讨厌了已经没有什么好害怕的了我才不是萝莉控呢......