【2020.11.30提高组模拟】剪辣椒(chilli) 题解

题意简述

给你一棵树,删去两条边,使得形成的三棵新树的大小极差最小化。求最小极差.

\(3\le n\le 200,000\).

Solution

假设根为\(1\).

删去的点意为这个点到其父亲的连边被删了,关系指一个点是另一个点的祖先,\(size_x\)为以\(x\)为根的子树大小,\(a,b,c\)是三棵新子树的大小。

答案即为

\[ans=max(a,b,c)-min(a,b,c)
\]

那么只会有两种情况:

被删去的点有关系

不妨设\(x\)是\(y\)的祖先

\[a=size_y,b=size_x-size_y,c=n-size_x
\]

被删去的点无关系

\[a=size_x,b=size_y,c=n-size_x-size_y
\]

显然这里就有一种比较暴力的方法了,时间复杂度\(O(n^2)\)。

考虑优化。

optimization

在\(dfs\)中,我们维护两个\(set:A,B\)

当进入点\(x\)时,把\(size_x\)放入\(A\)中;

当走出点\(x\)时,把\(size_x\)从\(A\)中删除并放入\(B\)中;

这样\(A\)里的元素就是\(x\)的直接祖先,\(B\)中是与\(x\)无关系的点(不需要考虑到还没有访问到的点,因为反过来会遍历到的)

接下来每到一个点\(x\),我们继续考虑两种情况:

被删去的点有关系

假如我们要删去点\(x\),另一个被删去的点为y应使得\(n-size_y\)和\(size_y-size_x\)这两个子树的大小最平均,即\(n-size_y=size_y-size_x\Rightarrow 2size_y=n+size_x\)。

我承认我图很丑,我谢罪……

那么我们就去\(A\)中找一个值接近上面\(size_y\)的值并更新答案。

当然,不一定会有正好相等的,应该用lower_bound()后在让指针iter--,进行两次判断。

被删去的点无关系

同理假如我们要删去点\(x\)和与它无关系的点\(y\),就要使得\(size_y\)和\(n-size_x-size_y\)这两个值最相近,即\(size_y=n-size_x-size_y\Rightarrow 2size_y=n-size_x\)。

我承认我图很丑,我再次谢罪……

那么我们就去\(B\)中找一个值接近上面\(size_y\)的值并更新答案。

Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
using namespace std; template<class T>inline void read(T&x)
{
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
x*=fu;
}
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do{G[++g]=x%10;x/=10;}while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
int n;
int ans=100000000;
set<int>A,B;
int sze[200010];
int head[400010],ver[400010],nxt[400010];
int cnt;
void insert(int x,int y)
{
nxt[++cnt]=head[x];
ver[cnt]=y;
head[x]=cnt; nxt[++cnt]=head[y];
ver[cnt]=x;
head[y]=cnt;
}
void dfs1(int x,int fa)
{
sze[x]=1;
for(int i=head[x];i;i=nxt[i])
{
if(ver[i]!=fa)
{
dfs1(ver[i],x);
sze[x]+=sze[ver[i]];
}
}
}
IL void upd(int x,int y,int z)
{
ans=min(ans,max({x,y,z})-min({x,y,z}));
}
void dfs2(int x,int fa)
{
// cout<<sze[x]<<endl;
A.insert(sze[x]);
set<int>::iterator iter;
iter=A.upper_bound((sze[x]+n)/2);
if(iter!=A.end())
{
upd(sze[x],*iter-sze[x],n-*iter);
}
if(iter!=A.begin())
{
iter--;
upd(sze[x],*iter-sze[x],n-*iter);
}
iter=B.upper_bound((n-sze[x])/2);
if(iter!=B.end())
{
upd(sze[x],*iter,n-sze[x]-*iter);
}
if(iter!=B.begin())
{
iter--;
upd(sze[x],*iter,n-sze[x]-*iter);
}
for(int i=head[x];i;i=nxt[i])
{
if(ver[i]!=fa)
{
dfs2(ver[i],x);
}
}
A.erase(sze[x]);
B.insert(sze[x]);
}
int main()
{
// freopen("chilli.in","r",stdin);
// freopen("chilli.out","w",stdout);
n=read();
for(int i=1;i<n;i++) insert(read(),read());
dfs1(1,0);
dfs2(1,0);
cout<<ans;
return 0;
}

End

一次性写完代码运行一下,没仔细看就以为自己WA了就来写Solution。写完Solution准备来Debug,写完的Debug语句再运行发现代码是对的!Woc泪目!


绝了,\(std\)是老外写的吧,全是c++11auto啥的

所以我也用了初始化列表+max(lists)

嘿嘿,还挺方便的呢


我在跑操的时候突然发现,这道题有些平衡树的思想。(而不是把\(set\)当成离散化bool数组来用)

不断的插入值,删除值,求前驱后继……不就是平衡树嘛?

看来我需要加强模型转化能力。

【2020.11.30提高组模拟】剪辣椒(chilli) 题解的更多相关文章

  1. 【2020.11.30提高组模拟】剪辣椒(chilli)

    剪辣椒(chilli) 题目描述 在花园里劳累了一上午之后,你决定用自己种的干辣椒奖励自己. 你有n个辣椒,这些辣椒用n-1条绳子连接在一起,任意两个辣椒通过用若干个绳子相连,即形成一棵树. 你决定分 ...

  2. JZOJ 【2020.11.30提高组模拟】剪辣椒(chilli)

    题目大意 给出一棵 \(n\) 个节点的树,删去其中两条边 使得分出的三个子树大小中最大与最小的差最小 分析 先一边 \(dfs\) 预处理出以 \(1\) 为根每个点的 \(size\) 然后按 \ ...

  3. 【2020.11.30提高组模拟】删边(delete)

    删边(delete) 题目 题目描述 给你一棵n个结点的树,每个结点有一个权值,删除一条边的费用为该边连接的两个子树中结点权值最大值之和.现要删除树中的所有边,删除边的顺序可以任意设定,请计算出所有方 ...

  4. 【2020.11.28提高组模拟】T1染色(color)

    [2020.11.28提高组模拟]T1染色(color) 题目 题目描述 给定 \(n\),你现在需要给整数 \(1\) 到 \(n\) 进行染色,使得对于所有的 \(1\leq i<j\leq ...

  5. 【2020.11.28提高组模拟】T2 序列(array)

    序列(array) 题目描述 ​给定一个长为 \(m\) 的序列 \(a\). 有一个长为 \(m\) 的序列 \(b\),需满足 \(0\leq b_i \leq n\),\(\sum_{i=1}^ ...

  6. JZOJ 6904. 【2020.11.28提高组模拟】T3 树上询问(query)

    题目 你有一棵 \(n\) 节点的树 ,回答 \(m\) 个询问,每次询问给你两个整数 \(l,r\) ,问存在多少个整数 \(k\) 使得从 \(l\) 沿着 \(l \to r\) 的简单路径走 ...

  7. 【2020.12.03提高组模拟】A组反思

    估计:40+10+0+0=50 实际:40+10+0+0=50 rank40 T1 赛时看到\(n,m\leq9\),我当机立断决定打表,暴力打了几个点之后发现在\(n\ne m\)且\(k\ne0\ ...

  8. 11.5NOIP2018提高组模拟题

    书信(letter) Description 有 n 个小朋友, 编号为 1 到 n, 他们每人写了一封信, 放到了一个信箱里, 接下来每个人从中抽取一封书信. 显然, 这样一共有 n!种拿到书信的情 ...

  9. 【2020.12.01提高组模拟】卡特兰数(catalan)

    题目 题目描述 今天,接触信息学不久的小\(A\)刚刚学习了卡特兰数. 卡特兰数的一个经典定义是,将\(n\)个数依次入栈,合法的出栈序列个数. 小\(A\)觉得这样的情况太平凡了.于是,他给出了\( ...

  10. 【2020.12.01提高组模拟】A组反思

    105,rk45 T1 赛时一开始先打了\(m=0\)的情况,也就是普通的卡特兰数,然后打了暴力,样例过了,把样例改改就不行了,原因没有保证是枚举的是合法的出栈序列 得分:\(WA\&TLE1 ...

随机推荐

  1. mac 触控板 三指拖动

    1. 打开系统偏好设置 点击屏幕左上角的苹果图标(),选择"系统设置". 2. 打开指针控制 在系统偏好设置窗口左侧栏中,点击"辅助功能",然后在右侧列表中, ...

  2. 使用Win32控制台实现boost共享内存通信

    发送端: #define BOOST_DATE_TIME_NO_LIB #include <boost/interprocess/shared_memory_object.hpp> #in ...

  3. Docker IPv6 网络环境配置

    由于目前Docker 在IPv6网络中运行的相关配置并非默认自动生成的,所以需要大家根据自己的网络环境来具体做一些相应配置,具体如下: 本次操作是在 Ubuntu16/18或者CentOS7 OS上面 ...

  4. ShardingSphere分组聚合,数据异常问题

    在使用ShardingSphere分组聚合时是,出现了数据汇总不正确问题.我这里只进行了分表,未进行分库.使用的是广播查询,因为是定时任务统计,无法使用到分片键.进行分组的字段是两个 1. SQL查询 ...

  5. Opencv环境配置一览

    OpenCV环境配置一览 专业相关,平时经常会使用到opencv的一些函数,目前主要包括Ubuntu系统,Android系统,本篇文章介绍在两个系统下对应的环境配置策略. Ubuntu环境 附上一个很 ...

  6. 【Maven】生命周期

    Maven 有三个相互独立的生命周期:Clean 生命周期.build 生命周期.site 生命周期. 各个构建环节执行的顺序:不能打乱顺序,必须按照既定的正确顺序来执行. Maven 的核心程序中定 ...

  7. exim4

    exim4 一台 debian 机器日常执行 apt update 后发现需要更新如下软件包, 之前没见过, 特此记录下. root@idebian:~# apt list --upgradable ...

  8. zk基础—3.集群与核心参数

    大纲 1.zk单机模式是如何启动的 2.zk集群是如何部署和启动的 3.zk集群部署要用什么样配置的机器 4.如何合理设置zk的JVM参数以及内存大小 5.zk配置的核心参数之tickTime.dat ...

  9. 关于CH182LED配置的说明

    CH182的LED配置有两种模式: 传统LED功能 该功能可通过页7寄存器19控制bit 3-5控制 使用时可将页7寄存器19 bit3 置0 通过bit4-5实现不同模式,默认情况下bit3为0,b ...

  10. 从DeepSeek看算法备案&大模型备案

    一.deepseek的备案情况 (一)算法备案情况 在算法备案系统网站上,北京深度求索人工智能基础技术研究有限公司和杭州深度求索人工智能基础技术研究有限公司分别进行了两个算法备案.从公司名称来看,正如 ...