[luogu6838]网络站点
对原树dfs,并按以下方式建立dfs序(深度从0开始):
1.若该点深度为偶数,则在递归到该点时将其加入dfs序
2.若该点深度为奇数,则在该点递归结束时将其加入dfs序
编号时,将每一个点在dfs序中的排名(从0开始)作为其编号
询问时,假设询问为$(x,y,S)$,并分类讨论:
1.若$|S|=1$,显然答案即该元素
2.若$x$深度为偶数,则$S$中所有元素均大于$x$,且$[x,S中次大值]$即$x$子树区间
若$y$在该区间中,则答案即$S$中$y$的后继,否则答案即$S$的最大值($x$的父亲)
特别的,若$x$为根节点,则将前者的次大值改为最大值(不存在父亲)
3.若$x$深度为奇数,做法类似前者
时间复杂度为$o(nq)$,可以通过
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 }