RT,大概的做法是不断暴力合并区间,具体实现看代码。
这么做没算错的话最差应该是 m 方的,但是大样例跑得飞快。有无正确复杂度证明或者 hack 数据。
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int now=0;
char ch=getchar();
while(!isdigit(ch))
ch=getchar();
while(isdigit(ch))
now=now*10+ch-'0',ch=getchar();
return now;
}
vector<int>ans;
const int maxn=2e6+10;
int l[maxn],r[maxn],n,m,x;
bool vis[maxn];
int query_merge(int l1,int l2,int r1,int r2)
{
return (min(r1,r2)-max(l1,l2)>=0);
}
int vis2[maxn];
void add(int k)
{
if(k==x)
return;
if(!vis2[k])
ans.push_back(k),vis2[k]=1;
}
void calc_left()
{
bool ok=1;
int nowl=x,nowr=x;
while(ok)
{
ok=0;
for(int i=1;i<=m;i++)
if(!vis[i])
{
if(query_merge(nowl,l[i],nowr,r[i]))
nowl=min(nowl,l[i]),add(l[i]),vis[i]=1,ok=1;
}
}
}
void calc_right()
{
memset(vis,0,sizeof vis);
bool ok=1;
int nowl=x,nowr=x;
while(ok)
{
ok=0;
for(int i=1;i<=m;i++)
if(!vis[i])
{
if(query_merge(nowl,l[i],nowr,r[i]))
nowr=max(nowr,r[i]),add(r[i]),vis[i]=1,ok=1;
}
}
}
main()
{
freopen("station.in","r",stdin);
freopen("station.out","w",stdout);
n=read(),m=read(),x=read();
for(int i=1;i<=m;i++)
l[i]=read(),r[i]=read();
calc_left();
calc_right();
sort(ans.begin(),ans.end());
for(auto x:ans)
cout<<x<<' ';
}
/*
7 5 4
3 4
4 6
1 3
5 7
4 6
*/