先分析答案,即$x$和$y$的关系有以下两种:
1.$y$在$x$子树中,那么答案即为包含$y$的$x$的儿子
2.$y$不在$x$子树中,那么答案即为$x$的父亲
那么第一个问题就是判断$y$是否在$x$的子树中,构造的思路有两个:1.记录每一个点到根的路径的状压;2.让每一个子树对应一个区间,记录该区间
前者显然行不通,考虑后者
为了找出这个区间,根最好是其中一个端点,之后考虑有哪些情况不可以:
1.当某两个兄弟(所包含区间相邻)为不同端点状态,那么无法区别这两个节点内部$y$属于哪棵子树
2.当子树的根与所有儿子端点状态相同,那么无法找到该子树所对应的区间
为了避免这两种情况,对于左端点的儿子,都需要记录右端点(反之同理),通过这个可以构造出一个dfs序列(不妨假定根的dfs序为1),考虑判定:
1.$x=1$(根),直接查找$S$中大于等于$y$的最小数即可
2.$|S|=1$(叶子),直接输出$S$中唯一的元素(父亲)即可
3.若$x<min S$,则$x$必然是左端点,令$z$为$S$中的次大值(其父亲为右端点,大于所有其他数):若$x< yle z$则答案为$S$中大于等于$y$的最小数,否则,答案为$S$中最大的数
4.若$x>max S$,则$x$必然是右端点,令$z$为$S$中的次小值(其父亲为左端点,小于所有其他数):若$zle y<x$则答案为$S$中小于等于$y$的最大数,否则,答案为$S$中最小的数

1 #include "stations.h" 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define N 1005 5 struct ji{ 6 int nex,to; 7 }edge[N<<1]; 8 int E,x,head[N],id[N]; 9 void add(int x,int y){ 10 edge[E].nex=head[x]; 11 edge[E].to=y; 12 head[x]=E++; 13 } 14 void dfs(int k,int fa,int s){ 15 if (!s)id[k]=++x; 16 for(int i=head[k];i!=-1;i=edge[i].nex) 17 if (edge[i].to!=fa)dfs(edge[i].to,k,s^1); 18 if (s)id[k]=++x; 19 } 20 vector<int> label(int n,int k,vector<int>u,vector<int>v){ 21 memset(head,-1,sizeof(head)); 22 for(int i=0;i<n-1;i++){ 23 add(u[i],v[i]); 24 add(v[i],u[i]); 25 } 26 x=0; 27 dfs(1,0,0); 28 } 29 int find_next_station(int x,int y,vector<int>s){ 30 if (x==1)return (*s.lower_bound(s.begin(),s.end(),y)); 31 if (s.size()==1)return s[0]; 32 if (x<s[0]){ 33 int z=s[s.size()-2]; 34 if ((x>=y)||(y>z))return s[s.size()-1]; 35 return (*s.lower_bound(s.begin(),s.end(),y)); 36 } 37 z=s[1]; 38 if ((z>y)||(y>=x))return s[0]; 39 return (*--s.upper_bound(s.begin(),s.end(),y)); 40 }