LOJ 6042 跳蚤王国的宰相

题意

跳蚤王国爆发了一场动乱,国王在镇压动乱的同时,需要在跳蚤国地方钦定一个人来做宰相。

由于当时形势的复杂性,很多跳蚤都并不想去做一个傀儡宰相,带着宰相的帽子,最后还冒着被打倒并杀头的危险,然而有一只跳蚤却想得与众不同最时尚。

本来他打算去教书,他已经发表了自己在学术方面的见解,获得了很多跳蚤们的赞同,但是这时听说跳蚤国要钦定宰相,他毅然打断了想去教书的想法,他觉得只要为了国家利益,自己的生死都可以不管,哪里能因为工作能给自己带来灾祸或者福分就去避开或者接近这份工作呢?所以他决定站出来接了这份工作。

然而当时国王的钦定方式很奇怪,跳蚤王国可以看作一棵树,国王认为宰相必须更好的为跳蚤服务,所以他会选择一个到所有节点距离和最小的节点,并在这个节点中钦定,如果有多个节点满足距离和最小则任选一个。

然而跳蚤国的动乱实在是太厉害了,以至于树的形态可能也会发生改变,也就是说,树上可能会有若干条边消失,如果这个情况出现的话一定会有同样数目的边出现,以保证整个结构仍然是一棵树

现在这个跳蚤想知道每个节点中的跳蚤如果要被钦定,至少需要多少条边消失(当然也会有同样数目的边出现)。作为这只跳蚤的一名真正的粉丝,你能帮他解决这个问题吗?

数据范围\(n\le 10^6\)

解题思路

为了行文方便,我们把一个一棵树称为过重的,当且仅当它的大小大于\(\frac{n}{2}\)

一个点是重心,当且仅当它的所有子树都不是过重的。

首先,对于这棵树的重心,它的答案一定为\(0\)。

对于非重心,它的过重的子树必然只有一个,且包含重心。

对于分裂出来的子树,我们把它接到我们期望它成为重心的点上一定不劣。

我们采取这样一种贪心的策略:先分裂重心的子树,从大到小。若某一时刻重心及重心的其他子树不过重,则可以把这一整颗树分裂出来。

接下来我们来证明这种策略的正确性。

首先,当重心以及重心的其他子树的大小不过重,而重心所在的子树依然过重,那么把重心分裂出来一定最优。

因为我们考虑到重心的任意一颗子树都不过重,那么只保留一颗子树一定是合法的。

我们把重心分裂出来其实就是保留重心的一颗子树的一部分,所以一定合法。

如果此时重心过重,那么重心所在的子树必定过重

所以必然要先把重心分裂到不过重

以上。

代码实现

我们把重心的所有子树按从大到小的顺序排序,然后二分。

就做完了。

#include<bits/stdc++.h>
#define now edge[i].v
#define go(x) for(int i=head[x];i;i=edge[i].nxt)
using namespace std;
const int sz=1e6+7;
const int inf=1e9;
int n;
int tot,rt;
int u,v,cnt;
int head[sz];
int ans[sz];
int mx[sz],siz[sz];
int s[sz],pos[sz],sum[sz];
struct Edge{
int v,nxt;
}edge[sz<<1];
void make_edge(int u,int v){
edge[++cnt]=(Edge){v,head[u]};head[u]=cnt;
edge[++cnt]=(Edge){u,head[v]};head[v]=cnt;
}
bool cmp(int x,int y){
return siz[x]>siz[y];
}
void getrt(int x,int fa){
siz[x]=1;
go(x) if(now!=fa){
getrt(now,x);
mx[x]=max(mx[x],siz[now]);
siz[x]+=siz[now];
}
mx[x]=max(mx[x],n-siz[x]);
if(mx[x]<tot) tot=mx[x],rt=x;
}
void dfs(int x,int fa){
siz[x]=1;
go(x) if(now!=fa){
dfs(now,x);
siz[x]+=siz[now];
}
}
void Dfs(int x,int fa,int id){
int w=n-siz[x];
if(n-siz[id]<=n/2) ans[x]=(x!=id);
else if(w-(sum[pos[id]-1])<=n/2){
int l=0,r=pos[id]-1;
while(l<r){
int mid=(l+r)>>1;
if(w-sum[mid]<=n/2||n-siz[id]-sum[mid-1]<=n/2) r=mid;
else l=mid+1;
}
ans[x]=l;
}
else{
int l=pos[id]+1,r=tot;
while(l<r){
int mid=(l+r)>>1;
if(w-sum[mid]+siz[id]<=n/2||n-sum[mid-1]<=n/2) r=mid;
else l=mid+1;
}
ans[x]=l-1;
}
go(x) if(now!=fa) Dfs(now,x,id);
}
void solve(){
tot=0;
go(rt) s[++tot]=now;
sort(s+1,s+tot+1,cmp);
for(int i=1;i<=tot;i++){
pos[s[i]]=i;
sum[i]=sum[i-1]+siz[s[i]];
}
go(rt) Dfs(now,rt,now);
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
make_edge(u,v);
}
tot=inf,rt=0;
getrt(1,0);
dfs(rt,0);
solve();
for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
}

LOJ 6042 跳蚤王国的宰相的更多相关文章

  1. 「雅礼集训 2017 Day7」跳蚤王国的宰相(树的重心)

    题面 来源 「 雅 礼 集 训 2017 D a y 7 」 跳 蚤 王 国 的 宰 相   传 统 2000   m s 1024   M i B {\tt「雅礼集训 2017 Day7」跳蚤王国的 ...

  2. 【思维题 细节】loj#6042. 「雅礼集训 2017 Day7」跳蚤王国的宰相

    挂于±1的细节…… 题目描述 跳蚤王国爆发了一场动乱,国王在镇压动乱的同时,需要在跳蚤国地方钦定一个人来做宰相. 由于当时形势的复杂性,很多跳蚤都并不想去做一个傀儡宰相,带着宰相的帽子,最后还冒着被打 ...

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

    我可以大喊一声这就是个思博题吗? 首先如果你能快速把握题目的意思后,就会发现题目就是让你求出每个点要成为树的重心至少要嫁接多少边 先说一个显然的结论,重心的答案为\(0\)(废话) 然后我们考虑贪心处 ...

  4. 【LOJ6042】「雅礼集训 2017 Day7」跳蚤王国的宰相(思博题)

    点此看题面 大致题意: 给你一棵树,询问对于每个点需要改变多少条边来使得它成为树中到所有点距离和最小的点. 一些初始化及想法 这是一道思博题. 首先我们要知道一个结论:对于这棵树的重心,它的答案必定为 ...

  5. ZJOI2019一轮停课刷题记录

    Preface 菜鸡HL终于狗来了他的省选停课,这次的时间很长,暂定停到一试结束,不过有机会二试的话还是可以搞到4月了 这段时间的学习就变得量大而且杂了,一般以刷薄弱的知识点和补一些新的奇怪技巧为主. ...

  6. [LOJ6029~6052]雅礼集训 2017 选做

    Link 代码可以在loj上看我的提交记录. Day 1 [LOJ6029]市场 对于一次除法操作,若区间内所有数的减少量均相同则可视作区间减法,否则暴力递归下去.显然一个线段树节点只会被暴力递归进去 ...

  7. 【HHHOJ】ZJOI2019模拟赛(十六)4.07 解题报告

    点此进入比赛 得分: \(100+100+100=300\) 排名: \(Rank\ 1\) \(Rating\): \(+13\)(\(\frac18Rated\)) 备注: 这场比赛全是做过的原题 ...

  8. loj 2955 「NOIP2018」保卫王国 - 树链剖分 - 动态规划

    题目传送门 传送门 想抄一个短一点ddp板子.然后照着Jode抄,莫名其妙多了90行和1.3k. Code /** * loj * Problem#2955 * Accepted * Time: 26 ...

  9. @loj - 2289@「THUWC 2017」在美妙的数学王国中畅游

    目录 @description@ @solution@ @accepted code@ @details@ @description@ n 个点编号 0 到 n-1,每个点有一个从 [0,1] 映射到 ...

随机推荐

  1. Spring - JUnit整合测试

    1.导包:test.jar - (依赖 aop.jar) 2.使用@RunWith注解创建spring容器 - @RunWith(SpringJUnit4ClassRunner.class) 3.使用 ...

  2. <剑指offer>面试题

    题目1:二维数组的查找 题目:在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断 ...

  3. mysql的建表约束

    主键约束(primary key) 主键约束能够唯一确定一张表中的记录,也就是可以通过某个字段添加约束,就可以是的该字段不重复,且不为空 create table user (id int prima ...

  4. CSS三大特性之继承性

    1.并不是所有的属性都可以继承,只有以color/font/text/line开头的属性 才可以继承. 2.在CSS的继承中,不仅仅是儿子可以继承,只要是后代都可以继承. 3.继承中的特殊性 3.1  ...

  5. UMP系统功能 容灾

  6. Java虚拟机性能管理神器 - VisualVM(7) 排查JAVA应用程序线程泄漏【转】

    Java虚拟机性能管理神器 - VisualVM(7) 排查JAVA应用程序线程泄漏[转] 标签: javajvm线程泄漏 2015-03-11 19:47 1098人阅读 评论(0) 收藏 举报   ...

  7. python中使用xlrd、xlwt操作excel

    python 对 excel基本的操作如下: # -*- coding: utf-8 -*- import xlrd import xlwt from datetime import date,dat ...

  8. 廖雪峰Java14Java操作XML和JSON-1XML-2DOM

    XML是一种数据表示形式. 可以描述非常复杂的数据数据结构 用于传输和传输数据 DOM:Document Object Model DOM模型就是把XML文档作为一个树形结构,从根结点开始,每个节点都 ...

  9. table方法也属于模型类的连贯操作方法之一

    table方法也属于模型类的连贯操作方法之一,主要用于指定操作的数据表. 用法 一般情况下,操作模型的时候系统能够自动识别当前对应的数据表,所以,使用table方法的情况通常是为了: 切换操作的数据表 ...

  10. 解决无法wifi上网的问题

    1.查看网卡型号 lspci | grep Network 可以看到我的是Wireless-AC 9560 2.登录Inter官网下载网卡驱动 https://www.intel.com/conten ...