[luogu6838]网络站点

先分析答案,即$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 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/13825838.html