对于一棵树(初始仅包含节点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$的路径即其子树中,询问结果为$ e u,r_{2i-1},r_{2i}$,再询问一次$(u,v,r_{2i-1})$即可
3.若$u$不为上述两种情况,询问结果为$v$,若$2ige d$则$u$为$v$的新儿子,否则令$i$增加1并重复此过程
(特别的,若$d$为奇数,我们认为$r_{d+1}=v$,且若为第二种情况,则一定在$r_{d}$到$v$的路径上)
下面,来考虑操作次数:
令$T(n)$为$n$个节点的子树中最大询问次数,考虑$u$结束的情况,即以下三种——
(为了方便,记$D=min(n-1,18)$,显然$dle D$)
1.在第一种情况下结束:假设在$i$时结束,则至多需要$T(s_{2i-1})+i$次(由于$s_{2i-1}ge s_{2i}$)
显然有$egin{cases}s_{i}le lfloorfrac{n}{2} floor&(i=1)\s_{i}le lfloorfrac{n-1}{i} floor&(2le ile d)end{cases}$,也即$T_{1}(n)=max(T(lfloorfrac{n}{2} floor)+1,max_{2le ile lceilfrac{D}{2} ceil}T(lfloorfrac{n-1}{2i-1} floor)+i)$
2.在第二种情况下结束:此时即询问$lceilfrac{d}{2} ceil+1$,即$T_{2}(n)=lceilfrac{D}{2} ceil+1$
3.在第三种情况下结束,此时即询问$lceilfrac{d}{2} ceil$次,同理即$T_{3}(n)=lceilfrac{D}{2} ceil$
最终$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 imes 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 }