首页 > 其他分享 >CF768G The Winds of Winter题解

CF768G The Winds of Winter题解

时间:2023-12-26 11:14:45浏览次数:31  
标签:sz fa int 题解 void son CF768G Winds op

我们考虑暴力咋做,每次得到一个森林之后,必定是从最大的树上摘一棵子树,挪到最小的树上,所以此时的答案为 \(max(siz_{mx}-x,siz_{mn}+x,siz_{次大值} )\),于是发现 \(x=\frac{siz_{mx}-siz_{mn}}{2}\) 时答案最优,所以只需找到这个值的前驱后继即可

我们使用 \(\text{multiset}\) 实现,分别维护当前子树内,当前点到根路径,以及其他的点的子树大小
第二个是好维护的,对于第一个也可以启发式合并解决
对于第三种操作,我们可以现将全部点扔进去,到这个点的时候再删去子树内的点,这也可以树上启发式合并

以及注意一些乱七八糟的 \(conner\)

code

#include<bits/stdc++.h>
using namespace std;
#define N 100055
int n,k,rt;
int ans[N],h[N],sz[N],son[N];
multiset<int> oth[2],q[N];
struct AB{
	int a,b,n;
}d[N*2];
void cun(int x,int y){
	d[++k]={x,y,h[x]},h[x]=k;
}
void add(int x,int op){
	oth[op].insert(sz[x]);
}
void del(int x,int op){
	auto it=oth[op].lower_bound(sz[x]);
	oth[op].erase(it);
}
void dfs(int x,int fa){
	sz[x]=1,son[x]=0;
	for(int i=h[x];i;i=d[i].n){
		int y=d[i].b;
		if(y==fa) continue;
		dfs(y,x);sz[x]+=sz[y];
		if(sz[y]>sz[son[x]]) son[x]=y;
	}
	add(x,0);
}
void dfs1(int x,int fa,int op){
	if(!op) del(x,0);
	else add(x,0);
	for(int i=h[x];i;i=d[i].n){
		int y=d[i].b;
		if(y==fa) continue;
		dfs1(y,x,op);
	}
}
void solve(int x,int fa,int fl){
	del(x,0),add(x,1);
	for(int i=h[x];i;i=d[i].n){
		int y=d[i].b;
		if(y==fa||y==son[x]) continue;
		solve(y,x,0);
	}
	if(son[x]) solve(son[x],x,1);
	sz[n+1]=n-sz[x];
	int mx1=0,mx2=0,mn=n+2;
	if(x!=rt) mx1=n+1,mn=n+1;
	for(int i=h[x];i;i=d[i].n){
		int y=d[i].b;
		if(y==fa) continue;
		if(sz[y]>=sz[mx1]) mx2=mx1,mx1=y;
		else if(sz[y]>=sz[mx2]) mx2=y;
		if(sz[y]<sz[mn]) mn=y;
		if(y==son[x]) continue;
		dfs1(y,x,0);
	}
	del(x,1);
	if(sz[mx1]==sz[mn]) ans[x]=sz[mn];
	else if(mx1==n+1){
		for(int o=0;o<=1;o++){
			auto it=oth[o].upper_bound((sz[mx1]-sz[mn])/2+o*sz[x]);
			if(it!=oth[o].end()){
				int siz=*it-o*sz[x];
				ans[x]=min(ans[x],max(sz[mx1]-siz,max(sz[mx2],sz[mn]+siz)));
			}
			if(it!=oth[o].begin()){
				it--;
				int siz=*it-o*sz[x];
				ans[x]=min(ans[x],max(sz[mx1]-siz,max(sz[mx2],sz[mn]+siz)));
			}
		}
	}
	else{
		auto it=q[mx1].upper_bound((sz[mx1]-sz[mn])/2);
		if(it!=q[mx1].end()){
			int siz=*it;
			ans[x]=min(ans[x],max(sz[mx1]-siz,max(sz[mx2],sz[mn]+siz)));
		}
		if(it!=q[mx1].begin()){
			it--;
			int siz=*it;
			ans[x]=min(ans[x],max(sz[mx1]-siz,max(sz[mx2],sz[mn]+siz)));
		}
	}
	if(!fl) dfs1(x,fa,1);
	if(son[x]){
		swap(q[x],q[son[x]]);
		for(int i=h[x];i;i=d[i].n){
			int y=d[i].b;
			if(y==fa||y==son[x]) continue;
			for(auto num:q[y]) q[x].insert(num);
			q[y].clear();
		}
	}
	q[x].insert(sz[x]);
}
int main(){
	scanf("%d",&n);
	if(n==1){
		printf("0\n");
		return 0;
	}
	for(int i=1,x,y;i<=n;i++){
		scanf("%d%d",&x,&y);
		if(!x||!y) rt=x|y;
		else cun(x,y),cun(y,x);
	}
	memset(ans,9,sizeof(ans));
	dfs(rt,0);sz[n+2]=n+1;
	solve(rt,0,0);
	for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
	return 0;
}

标签:sz,fa,int,题解,void,son,CF768G,Winds,op
From: https://www.cnblogs.com/hubingshan/p/17927676.html

相关文章

  • HNOI2017影魔题解
    HNOI2017影魔对于两种贡献,都只用考虑左边第一个比自己大的,和右边第一个比自己大的数,分别记为\(l_i、r_i\)对于询问一,每个数对\((l_i,r_i)\)构成全部情况对于询问二,可以拆分成\(x=l_i\)时,\(y\in[i+1,r_i-1]\),以及\(y=r_i\)时,\(x\in[l_i+1,i-1]\)我们考虑用扫描线......
  • 软件测试/测试开发|selenium NoSuchDriverException问题解决
    前言我们在使用selenium进行web自动化测试时,有时候会遇到NoSuchDriverException的问题,这个异常通常是由于WebDriver无法找到指定的浏览器驱动而引起的。在这篇文章中,我们将讨论NoSuchDriverException的原因以及如何解决这个问题。NoSuchDriverException是什么?NoSuchDriverExce......
  • CF1051C Vasya and Big Integers 题解
    Problem-1051E-CodeforcesVasyaandBigIntegers-洛谷感谢女队提交记录推荐给我的一道题\(Orz\)首先\(O(n^2)\)的\(dp\)是simple的,如果你没看出来你可能是像我一样把题目看错了设\(dp_i\)表示考虑前\(i\)个的方案数,转移枚举长度后比较字典序。虽然看......
  • P6922 [ICPC2016 WF] Longest Rivers 题解
    Description有\(n\)条河和\(m+1\)个交汇处构成一棵以\(0\)号点(即大海)为根的树。每条河有各自的名称。对于一个交汇处,从它流出的干流的名称是流入这个交汇处的各个支流的名称之一。一条河流的长度是以它为名称的河流的长度之和。对于一个可能的命名方案,一条河流的排名等于......
  • SOJ1972 题解
    题意设\(S\)为一个可重数集,满足所有元素均为非负整数。你可以对\(S\)进行若干次(可以为\(0\)次)如下操作:选择一个非负整数\(x\)满足\(x\)至少在\(S\)中出现了\(2\)次,在\(S\)中删除一个\(x\),并将\((x-1)\)或\((x+1)\)插入\(S\)。如果你选择插入\((x-1)\),你必......
  • VS2022远程调试Linux程序卡住问题解决
    问题:说明:使用vs2022第一次远程调试linux上的程序时,会出现调试器启动时卡住问题。原因就是第一次调试时,会在目标服务器下下载vsdbg工具,因为下载源在国外,所以下载特别慢,就会造成卡住的现象。解决:uname-m 查看远程调试时,用户文件夹下会多一个.vs-debugger隐藏文件夹,如果是使用......
  • 【已解决-实操篇】SaTokenException: 非Web上下文无法获取Request问题解决-实操篇
    在上一篇《【理论篇】SaTokenException:非Web上下文无法获取Request问题解决-理论篇》中,凯哥(凯哥Java)介绍了产生这个问题的源码在哪里,以及怎么解决的方案。没有给出实际操作步骤。本文,凯哥就通过threadLocal方案来解决。一、创建用于存放共享变量的对象代码如下:packagecom.kai......
  • [SDOI2010] 大陆争霸 题解
    [题目传送门](https://www.luogu.com.cn/problem/P2446)#解法由题可知,一个城市$u$保护城市$v$,所以建一条边$u\tov$表示城市$u$保护城市$v$,因为题目说保证有解,所以建的图一定是一个**有向无环图$DAG$**。再在此基础上求出最短路径。具体过程为设$dis_u$表示实际到达(攻破)$u$的最......
  • 「HCOI-R1」报名人数 题解
    博客园。我们会发现,\(2\)和\(3\)的火柴个数是一样的,\(9\)和\(0\)的火柴个数是一样的。所以只有在\(12\)到\(13\)这样是合法的,自己推一下可以知道,最多只有连续两个。而在\(l\)到\(r\)的长度大于\(9\)的时候可以直接输出\(2\)。剩下的情况直接暴力枚举即可。#......
  • CF contest 1909 Pinely Round 3 (Div. 1 + Div. 2) 题解(Vanilla的掉分赛)
    CFcontest1909PinelyRound3(Div.1+Div.2)Vanilla的掉分赛绪言PinelyRound3(Div.1+Div.2)-Codeforces\[\color{purple}\large\textbf{世界上只有一种真正的英雄主义,}\]\[\color{red}\large\textbf{就是认清了生活的真相后还依然热爱它。}\]\[\color{gray}......