[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 }
View Code

 

posted @ 2020-10-16 12:35  PYWBKTDA  阅读(131)  评论(0编辑  收藏  举报