Link:
A:
为了保证复杂度明显是从终结点往回退
结果一开始全在想优化建边$dfs$……其实可以不用建边直接$multiset$找可行边跑$bfs$就行了
由于保证每个点只进队列一次、被搜索到一次,因此复杂度为$O(n*log(n))$
#include <bits/stdc++.h> using namespace std; #define X first #define Y second typedef long long ll; typedef pair<int,int> P; typedef double db; const int MAXN=2e5+10; queue<int> q; multiset<P>::iterator it; multiset<P> sa,sb; int n,d,dist[MAXN],a[MAXN],b[MAXN]; int main() { scanf("%d%d",&n,&d); for(int i=1;i<=2*n;i++) scanf("%d%d",&a[i],&b[i]),a[i]=-a[i],b[i]=-b[i],dist[i]=-1; for(int i=1;i<=n;i++) { if(b[i]==0) q.push(i),dist[i]=1; else sa.insert(P(b[i],i)); if(a[n+i]==0) q.push(n+i),dist[n+i]=1; else sb.insert(P(a[n+i],n+i)); } while(!q.empty()) { int t=q.front();q.pop(); if(t<=n) { while(true) { it=sb.lower_bound(P(a[t],0)); if(it==sb.end()||(*it).X-a[t]>d) break; dist[(*it).Y]=dist[t]+1; q.push((*it).Y);sb.erase(it); } } else { while(true) { it=sa.lower_bound(P(b[t],0)); if(it==sa.end()||(*it).X-b[t]>d) break; dist[(*it).Y]=dist[t]+1; q.push((*it).Y);sa.erase(it); } } } for(int i=1;i<=n;i++) printf("%d\n",dist[i]); return 0; }