這題最關鍵的是如何跳過無用結點
可以用鏈表,每一個結點指向它或它右側的可用結點
但是查找悲劇
所以,我們可以用並查集,把所有結點指向[它或它右側的可用結點]
這樣就可以直接跳過,注意 根為最右側可用結點,其它結點為它左側所有刪去的點
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #include<cmath> #include<cctype> #include<cassert> #include<climits> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define ForD(i,n) for(int i=n;i;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define RepD(i,n) for(int i=n;i>=0;i--) #define MEM(a) memset(a,0,sizeof(a)) #define MEMI(a) memset(a,127,sizeof(a)) #define MEMi(a) memset(a,128,sizeof(a)) #define INF (2139062143) #define F (1000000009) #define MAXN (1000000+10) #define Read(x) {x=0;\ while (isdigit(c=getchar())) x=x*10+c-48;} typedef long long ll; int n,s,l[MAXN],r[MAXN]; int father[MAXN]; int st[MAXN]; char c; int getfather(int x) { int size=1;st[1]=x; while (st[size]&&father[st[size]]^st[size]) { st[size+1]=father[st[size]]; size++; } For(i,size-1) father[st[i]]=st[size]; return father[x]; } bool b[MAXN]={0}; int q[MAXN],d[MAXN]; void bfs(int s) { For(i,n) d[i]=-1; d[s]=0;q[1]=s;b[s]=1;father[s]=s+1; int head=1,tail=1; while (head<=tail) { int now=q[head]; // cout<<now<<endl; for(int i=l[now];i<=r[now]&&i;) { if (!b[i]) b[i]=1,d[i]=d[now]+1,father[i]=i+1,q[++tail]=i; i=getfather(i); } head++; } } int main() { freopen("travel.in","r",stdin); freopen("travel.out","w",stdout); Read(n) Read(s) father[0]=0; For(i,n) { Read(l[i]) Read(r[i]) father[i]=i; } bfs(s); For(i,n) printf("%d\n",d[i]); // while(1); return 0; }