[loj3031]聚会
对于一棵树(初始仅包含节点0),不断加入一个不在树中的节点$u$(不需要随机),并维护这棵树
具体的,对这棵树点分治,假设当前重心$v$有$d$个子树,假设其中第$i$个子树根为$r_{i}$,子树大小为$s_{i}$,且不妨假设子树大小单调不上升(即$s_{1}\ge s_{2}\ge ...\ge s_{d}$)
初始令$i=1$,并询问$(u,r_{2i-1},r_{2i})$,并分类讨论:
1.若$u$在$r_{2i-1}$或$r_{2i}$的子树中,询问结果为$r_{2i-1}$或$r_{2i}$,递归询问结果的子树即可
2.若$u$在$r_{2i-1}$或$r_{2i}$到$v$的路径即其子树中,询问结果为$\ne u,r_{2i-1},r_{2i}$,再询问一次$(u,v,r_{2i-1})$即可
3.若$u$不为上述两种情况,询问结果为$v$,若$2i\ge d$则$u$为$v$的新儿子,否则令$i$增加1并重复此过程
(特别的,若$d$为奇数,我们认为$r_{d+1}=v$,且若为第二种情况,则一定在$r_{d}$到$v$的路径上)
下面,来考虑操作次数:
令$T(n)$为$n$个节点的子树中最大询问次数,考虑$u$结束的情况,即以下三种——
(为了方便,记$D=\min(n-1,18)$,显然$d\le D$)
1.在第一种情况下结束:假设在$i$时结束,则至多需要$T(s_{2i-1})+i$次(由于$s_{2i-1}\ge s_{2i}$)
显然有$\begin{cases}s_{i}\le \lfloor\frac{n}{2}\rfloor&(i=1)\\s_{i}\le \lfloor\frac{n-1}{i}\rfloor&(2\le i\le d)\end{cases}$,也即$T_{1}(n)=\max(T(\lfloor\frac{n}{2}\rfloor)+1,\max_{2\le i\le \lceil\frac{D}{2}\rceil}T(\lfloor\frac{n-1}{2i-1}\rfloor)+i)$
2.在第二种情况下结束:此时即询问$\lceil\frac{d}{2}\rceil+1$,即$T_{2}(n)=\lceil\frac{D}{2}\rceil+1$
3.在第三种情况下结束,此时即询问$\lceil\frac{d}{2}\rceil$次,同理即$T_{3}(n)=\lceil\frac{D}{2}\rceil$
最终$T(n)=\max(T_{1}(n),T_{2}(n),T_{3}(n))$,初始状态为$T(1)=0$(此时将$u$作为该点的儿子即可),最大询问次数为$\sum_{i=1}^{n-1}T(i)$
经过计算,可得在$n=2\times 10^{3}$时,该值为39371(官方题解给出的值是39632),可以通过


1 #include<bits/stdc++.h>
2 #include "meetings.h"
3 using namespace std;
4 #define N 2005
5 struct Edge{
6 int nex,to;
7 }edge[N<<1];
8 vector<int>v;
9 int E,rt,head[N],vis[N],sz[N],Vis[N];
10 bool cmp(int x,int y){
11 return sz[x]>sz[y];
12 }
13 void add(int x,int y){
14 edge[E].nex=head[x];
15 edge[E].to=y;
16 head[x]=E++;
17 }
18 void get_sz(int k,int fa){
19 sz[k]=1;
20 for(int i=head[k];i!=-1;i=edge[i].nex)
21 if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
22 get_sz(edge[i].to,k);
23 sz[k]+=sz[edge[i].to];
24 }
25 }
26 void get_rt(int k,int fa,int s){
27 int mx=s-sz[k];
28 for(int i=head[k];i!=-1;i=edge[i].nex)
29 if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
30 get_rt(edge[i].to,k,s);
31 mx=max(mx,sz[edge[i].to]);
32 }
33 if (mx<=s/2)rt=k;
34 }
35 void dfs(int k,int u){
36 get_sz(k,0);
37 get_rt(k,0,sz[k]);
38 get_sz(rt,0);
39 vis[rt]=1;
40 v.clear();
41 for(int i=head[rt];i!=-1;i=edge[i].nex)
42 if (!vis[edge[i].to])v.push_back(edge[i].to);
43 sort(v.begin(),v.end(),cmp);
44 if (v.size()&1)v.push_back(rt);
45 for(int i=0;i<v.size();i+=2){
46 int ans=Query(u,v[i],v[i+1]);
47 if (ans==rt)continue;
48 if ((ans==v[i])||(ans==v[i+1])){
49 dfs(ans,u);
50 return;
51 }
52 int p=v[i];
53 if (Query(u,rt,v[i])==rt)p=v[i+1];
54 add(ans,rt),add(ans,p);
55 for(int j=head[rt];j!=-1;j=edge[j].nex)
56 if (edge[j].to==p){
57 edge[j].to=ans;
58 break;
59 }
60 for(int j=head[p];j!=-1;j=edge[j].nex)
61 if (edge[j].to==rt){
62 edge[j].to=ans;
63 break;
64 }
65 if (ans!=u){
66 add(u,ans);
67 add(ans,u);
68 Vis[ans]=1;
69 }
70 return;
71 }
72 add(rt,u),add(u,rt);
73 }
74 void Solve(int n){
75 memset(head,-1,sizeof(head));
76 for(int i=1;i<n;i++)
77 if (!Vis[i]){
78 memset(vis,0,sizeof(vis));
79 dfs(0,i);
80 }
81 for(int i=0;i<n;i++)
82 for(int j=head[i];j!=-1;j=edge[j].nex)
83 if (i<edge[j].to)Bridge(i,edge[j].to);
84 }
[loj3031]聚会的更多相关文章
- BSD和云 – 不可错过的BSD聚会
自2012年开始,微软云计算与企业事业部和Citrix思杰,NetApp达成合作,共同开发出第一版针对Hyper-V虚拟设备驱动以及相关的用户态程序,并将此称之为集成服务 (Integration S ...
- 【BZOJ-1787&1832】Meet紧急集合&聚会 倍增LCA
1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 2259 Solved: 1023[Submit] ...
- bzoj-3170 3170: [Tjoi 2013]松鼠聚会(计算几何)
题目链接: 3170: [Tjoi 2013]松鼠聚会 Time Limit: 10 Sec Memory Limit: 128 MB Description 有N个小松鼠,它们的家用一个点x,y表 ...
- DHV 平常语言对话 一次聚会离场
一次聚会离场 一次聚会离场,如果顺路要计划好A女生 和B女生 或者C女闺密一起回去,然后再自己回去 如果别人说:好男人, 自己一定要谦虚说: 哪里,好男人一般都是备胎. 到家了要说: 不是说: 我:我 ...
- BZOJ3170: [Tjoi 2013]松鼠聚会
3170: [Tjoi 2013]松鼠聚会 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 531 Solved: 249[Submit][Statu ...
- bzoj1832: [AHOI2008]聚会
写过的题... #include<cstdio> #include<cstring> #include<iostream> #include<algorith ...
- BZOJ 3170: [Tjoi 2013]松鼠聚会 切比雪夫距离
3170: [Tjoi 2013]松鼠聚会 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...
- tyvj1161聚会的名单(trie树)
背景 Background 明天就是candy的生日,candy又会邀请自己的一大堆好友来聚会了!哎!又要累坏飘飘乎居士了!! 描述 Description 明天就是candy的生日.晚上,c ...
- BZOJ 1037 [ZJOI2008]生日聚会Party
1037: [ZJOI2008]生日聚会Party Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1583 Solved: 936[Submit][ ...
随机推荐
- 关于十二生肖的数学发现(C++)
把数字看成是年份,然后根据生肖赋值.这里把鼠年赋值为1,牛年赋值为2,虎年赋值为3,兔年赋值为4,龙年赋值为5,蛇年赋值为6,马年赋值为7,羊年赋值为8,猴年赋值为9,鸡年赋值为10,狗年赋值为11, ...
- 5分钟让你掌握Vuex,深入浅出
5分钟让你掌握Vuex,深入浅出 一.什么是Vuex? 概念:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预 ...
- 更好的 java 重试框架 sisyphus 的 3 种使用方式
回顾 我们前面学习了 更好的 java 重试框架 sisyphus 入门简介 更好的 java 重试框架 sisyphus 配置的 2 种方式介绍 更好的 java 重试框架 sisyphus 背后的 ...
- 【数据结构与算法Python版学习笔记】查找与排序——散列、散列函数、区块链
散列 Hasing 前言 如果数据项之间是按照大小排好序的话,就可以利用二分查找来降低算法复杂度. 现在我们进一步来构造一个新的数据结构, 能使得查找算法的复杂度降到O(1), 这种概念称为" ...
- springcloud整合seata
springcloud整合seata 一.背景 二.项目结构 三.实现功能: 四.项目使用到的技术 五.整合步骤 1.引入spring-cloud-starter-alibaba-seata jar包 ...
- Noip模拟61 2021.9.25
T1 交通 考场上想了一个$NPC$.应该吧,是要求出图里面的所有可行的不重复欧拉路 无数种做法都无法解出,时间也都耗在这个上面的,于是就考的挺惨的 以后要是觉得当前思路不可做,就试着换一换思路,千万 ...
- Linux多线程编程之详细分析
线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步.互斥,这些东西将在本文中介绍.我见到这样一道面试题: 是否熟悉POSIX多线程 ...
- 对SQLServer错误使用聚集索引的优化案例(千万级数据量)
前言: 半个月前发了文章 SQLServer聚集索引导致的插入性能低 终于等到生产环境休整半天,这篇文章是对前文的实际操作. 以下正文开始: 异常:近期发现偶尔有新数据插入超时. 分析:插入条码有多种 ...
- 平衡二叉树检查 牛客网 程序员面试金典 C++ Python
平衡二叉树检查 牛客网 程序员面试金典 C++ Python 题目描述 实现一个函数,检查二叉树是否平衡,平衡的定义如下,对于树中的任意一个结点,其两颗子树的高度差不超过1. 给定指向树根结点的指针T ...
- 重学STM32---(十)之CAN通信(二)
目录 前言 程序编写 主代码 测试 前言 CAN协议是非常难的,但是在stm32中却是简单的,只需要我们配置寄存器即可,,,即使这样,我在学习的时候也遇到了许多困难 程序编写 1.开时钟,不用说 ...