Link:

USACO 2017 Dec Gold 传送门

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;
}
Problem A

相关文章:

  • 2022-12-23
  • 2021-07-12
  • 2021-12-26
  • 2022-01-29
  • 2021-05-19
  • 2022-01-16
  • 2021-08-21
  • 2021-07-20
猜你喜欢
  • 2021-06-24
  • 2021-08-09
  • 2021-10-13
  • 2021-09-25
  • 2021-10-18
  • 2021-12-01
  • 2021-09-26
相关资源
相似解决方案