[loj3347]有趣的旅途
考虑求出重心,以0为根建树,求出第 $i$个点的子树大小$sz[i]$($a(0,i)$),则满足$n-sz[i]\le \lfloor\frac{n}{2}\rfloor$的$sz[i]$中的最小值必然合法
证明:反证法,若其不合法,则其必然有一棵子树$sz[k]>sz[son]>\lfloor \frac{n}{2}\rfloor$,那么$sz[son]$也满足该条件且更小,矛盾
设重心为$r$,再求出每一个点的深度$d[i]$($h(r,i)$),以及在$r$的哪一个儿子的子树内(若$r$有三个儿子,询问其中两个即可),至此共计最多为$4(n-1)$次询问,在$Q$的范围之内
考虑构造,构造的基本思路有3点:1.保证任意时刻$r$都为重心;2.任意相邻两点在$r$不同子树中;3.保证位置同奇偶(如第2和4个)的点深度不上升(很明显这样可以保证充分性)
(根据思路1,可以发现最终必然只会剩下$r$,再将$r$加入旅程中即可)
先保证思路1和2,$r$为重心当且仅当$sz_{max}\le \sum sz_{other}+1$,而当$\sum sz_{other}<sz_{max}$时,可以将另外的子树合并起来,从$sz_{max}$开始(否则会不够用),依次修改这颗子树中和其他子树中的点即可
每一次修改,对于$sz_{max}-\sum sz_{other}$的变化具有连续性,且最后一次修改必然不是在$sz_{max}$中(否则修改前也可以),因此通过这样的操作就可以保证思路1和2
再保证思路3,构造方式是不断选择其他子树中最深的点,这样做的正确性证明如下:
记$a_{i}$为第$i$次所选子树编号,$v_{i}$为第$i$次所选的点深度,那么若$a_{i}=a_{i+2}$则显然有$v_{i}\ge v_{i+2}$,否则由于$a_{i}\ne a_{i+2}$,则$v_{i+1}\ge v_{i+2}$(否则第$i+1$会选$a_{i+2}$),那么若$a_{i}<a_{i+2}\le a_{i+1}$,不论$a_{i-1}=a_{i+2}或a_{i+1}$,另一个权值一定更大,而不会选$a_{i}$
在$\sum sz_{other}<sz_{max}$的过程中,对每一棵子树都选择最深的点,同奇偶的点必然是在同一棵子树中,因此满足该性质
当两者交界时,记$x$表示选择$sz_{max}$的那一次,那么可能会有$v_{x-1}<v_{x+1}$,不满足思路3的要求
考虑第$x-2$次操作,必然有$a_{x-2}=a_{x+1}$(否则可以选$v_{x+1}$),那么我们可以撤销这次操作,并直接进入交替选$sz_{max}$的过程,这样就有$sz_{max}=\sum sz_{other}$,显然也是可行的

1 #include "fun.h"
2 #include<bits/stdc++.h>
3 using namespace std;
4 #define N 100005
5 vector<int>v_son,ans,v[3];
6 int r,n,sz[N],d[N];
7 bool cmp(int x,int y){
8 return d[x]<d[y];
9 }
10 bool pd(int x,int y,int z){
11 int s=max(max(x,y),z);
12 return x+y+z-s<s;
13 }
14 void push(int k){
15 ans.push_back(v[k].back());
16 v[k].pop_back();
17 }
18 vector<int> createFunTour(int nn,int q){
19 n=nn;
20 sz[r=0]=n;
21 for(int i=1;i<n;i++){
22 sz[i]=attractionsBehind(0,i);
23 if ((n-sz[i]<=n/2)&&(sz[r]>sz[i]))r=i;
24 }
25 for(int i=0;i<n;i++)
26 if (i!=r){
27 d[i]=hoursRequired(r,i);
28 if (d[i]==1)v_son.push_back(i);
29 }
30 for(int i=0;i<n;i++){
31 if (i==r)continue;
32 bool flag=0;
33 for(int j=1;j<v_son.size();j++)
34 if ((i==v_son[j])||(hoursRequired(v_son[j],i)==d[i]-1)){
35 v[j].push_back(i);
36 flag=1;
37 break;
38 }
39 if (!flag)v[0].push_back(i);
40 }
41 for(int i=0;i<v_son.size();i++)sort(v[i].begin(),v[i].end(),cmp);
42 if (v[0].size()<v[1].size())swap(v[0],v[1]);
43 if (v[0].size()<v[2].size())swap(v[0],v[2]);
44 for(int i=-1;;){
45 if (pd(v[0].size(),v[1].size(),v[2].size()))break;
46 if (i>=0)push(i);
47 int p=i;
48 i=-1;
49 for(int j=0;j<v_son.size();j++)
50 if ((j!=p)&&(v[j].size())&&((i<0)||(d[v[i].back()]<d[v[j].back()])))i=j;
51 }
52 if (v[0].size()<v[1].size())swap(v[0],v[1]);
53 if (v[0].size()<v[2].size())swap(v[0],v[2]);
54 for(int i=0;i<v[2].size();i++)v[1].push_back(v[2][i]);
55 sort(v[1].begin(),v[1].end(),cmp);
56 if ((ans.size())&&(v[1].size())&&(d[ans.back()]<d[v[1].back()])){
57 v[1].push_back(ans.back());
58 ans.pop_back();
59 sort(v[1].begin(),v[1].end(),cmp);
60 }
61 while (v[0].size()){
62 push(0);
63 if (v[1].size())push(1);
64 }
65 ans.push_back(r);
66 return ans;
67 }
[loj3347]有趣的旅途的更多相关文章
- [APIO2020]有趣的旅途
注意到第一个点是可以钦定的. 那么我们考虑在重心的子树里反复横跳. 每次选择不同子树里的深度最大的点. 在同一颗子树里可能会在lca处出现问题. 那么我们选择重心,要考虑到会不会出现一颗子树不够选的操 ...
- 谈谈一些有趣的CSS题目(十二)-- 你该知道的字体 font-family
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
- 谈谈一些有趣的CSS题目(十一)-- reset.css 知多少?
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
- 几个有趣的WEB设备API(二)
浏览器和设备之间还有很多有趣的接口, 1.屏幕朝向接口 浏览器有两种方法来监听屏幕朝向,看是横屏还是竖屏. (1)使用css媒体查询的方法 /* 竖屏 */ @media screen and (or ...
- 谈谈一些有趣的CSS题目(三)-- 层叠顺序与堆栈上下文知多少
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 谈谈一些有趣的CSS题目(一)-- 左边竖条的实现方法
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 谈谈一些有趣的CSS题目(二)-- 从条纹边框的实现谈盒子模型
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 谈谈一些有趣的CSS题目(四)-- 从倒影说起,谈谈 CSS 继承 inherit
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 谈谈一些有趣的CSS题目(五)-- 单行居中,两行居左,超过两行省略
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
随机推荐
- 硝烟中的Scrum和XP
硝烟中的Scrum和XP 初次接触Scrum和XP(更加准确的说是"看到"),心里不免有些疑问,软件开发为什么会有如此多的方式,难道软件开发.软件工程不就是写写代码的事儿吗?直到后 ...
- 通过Swagger文档生成前端service文件,提升前端开发效率
在企业级的项目开发过程中,一般会采用前后端分离的开发方式,前后端通过api接口进行通信,所以接口文档就显得十分的重要. 目前大多数的公司都会引入Swagger来自动生成文档,大大提高了前后端分离开发的 ...
- 原生js-无缝滚动
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- QG-2019-AAAI-Improving Neural Question Generation using Answer Separation
Improving Neural Question Generation using Answer Separation 本篇是2019年发表在AAAI上的一篇文章.该文章在基础的seq2seq模型的 ...
- 机器学习:KNN
KNN:K-nearst neighbors 简介: k-近邻算法采用测量不同特征值之间的距离来进行分类,简而言之为:人以类聚,物以群分 KNN既可以应用于分类中,也可用于回归中:在分类的预测是,一般 ...
- [对对子队]会议记录5.24(Scrum Meeting10)
今天已完成的工作 梁河览 工作内容:修改第一关的新手引导 相关issue:优化初步导出版本 相关签入:fix:改进第一关的新手引导 何瑞 工作内容:为加速按钮添加锚点 相关issu ...
- 2021.8.16考试总结[NOIP模拟41]
T1 你相信引力吗 肯定是单调栈维护.但存在重复值,还是个环,不好搞. 发现取区间时不会越过最大值,因此以最大值为断点将环断为序列.在栈里维护当前栈中有多少个与当前元素相等的元素,小分类讨论一下. 最 ...
- 常见SOC启动流程分析
本文以s5pv210这款SOC为例,分析了其启动流程 在s5pv210的SOC内部,存在着一个内部的ROM和一个内部的RAM 这个内部的ROM叫做 IROM,它是norflash的一种.其不同于板子上 ...
- .NET 5 全自动分表组件,.NET 分表方案 ,分表架构与设计
一.疑问&目的 1.1 分表使用场景 (1)可扩展架构设计,比如一个ERP用5年不卡,到了10就卡了因为数据太多了,这个时候很多人都是备份然后清空数据,这个工作大并且麻烦,以前的数据很难在使用 ...
- 编译内核错误:Can't use 'defined(@array)' (Maybe you should just omit the defined()?) at kernel/timeconst.pl line 373
最近在编译一个新的rk sdk的时候,编译内核报错 CHK include/linux/version.h CHK include/generated/utsrelease.h make[1]: 'i ...