题目链接:https://www.luogu.com.cn/problem/P4083
开始时 A A A和 B B B各有两个礼物,每个礼物对两个人有不同的价值,开始时 A A A会送 B B B一个礼物。
对于一个收到礼物的人,如果该礼物对他来说价值为 v a l val val,那么他会回送一个对于他来说 [ v a l , v a l + d ] [val,val+d] [val,val+d]这个范围内的礼物。
直到某个人收到价值为 0 0 0的礼物就停止,求对于 A A A开始送的每个礼物,最少要互送多少个礼物才能停止
我们可以发现其实就是每次对于一个区间内连边然后求最短路。
我们对于 A A A和 B B B各自开一棵线段树然后优化一下连边,从价值为 0 0 0的礼物开始跑,之后直接输出每个礼物的最短路即可
#include
#include
#include
#include
#include
using namespace std;
const int N=1e5*20;
struct node{
int to,next,w;
}a[N*2];
struct gnode{
int x,y,w,id;
}g[N],b[N];
int n,d,num,tot,cnt,rt0,rt1;
int ls[N],in[N],f[N],w[N];
int lson[N],rson[N],v1[N],v2[N];
bool vis[N];
queue<int> q;
void addl(int x,int y,int w){
a[++tot].to=x;
a[tot].next=ls[y];
a[tot].w=w;ls[y]=tot;
}
void Build(int &x,int l,int r,int z){
x=++num;
if(l==r){
if(z)addl(x,g[l].id,0);
else addl(x,b[l].id,0);
return;
}
int mid=(l+r)>>1;
Build(lson[x],l,mid,z);
Build(rson[x],mid+1,r,z);
addl(x,lson[x],0);addl(x,rson[x],0);
return;
}
void Change(int x,int L,int R,int l,int r,int pos){
if(l>r)return;
if(L==l&&R==r)
{addl(pos,x,1);return;}
int mid=(L+R)>>1;
if(r<=mid)Change(lson[x],L,mid,l,r,pos);
else if(l>mid)Change(rson[x],mid+1,R,l,r,pos);
else Change(lson[x],L,mid,l,mid,pos),Change(rson[x],mid+1,R,mid+1,r,pos);
return;
}
void SPFA(){
while(!q.empty()){
int x=q.front();q.pop();
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(f[x]+a[i].w<f[y]){
f[y]=f[x]+a[i].w;
if(!vis[y]){
q.push(y);
vis[y]=1;
}
}
}
vis[x]=0;
}
}
bool cmp1(gnode x,gnode y)
{return x.x<y.x;}
bool cmp2(gnode x,gnode y)
{return x.y<y.y;}
int main()
{
scanf("%d%d",&n,&d);
for(int i=1;i<=n;i++)
scanf("%d%d",&b[i].x,&b[i].y),b[i].id=i;
for(int i=1;i<=n;i++)
scanf("%d%d",&g[i].x,&g[i].y),g[i].id=i+n;
sort(b+1,b+1+n,cmp1);
sort(g+1,g+1+n,cmp2);
num=n*2;
Build(rt0,1,n,0);
Build(rt1,1,n,1);
for(int i=1;i<=n;i++)v1[i]=b[i].x;
for(int i=1;i<=n;i++)v2[i]=g[i].y;
sort(b+1,b+1+n,cmp2);
sort(g+1,g+1+n,cmp1);
int link=1;
memset(f,0x3f,sizeof(f));
for(int i=1;i<=n;i++){
int l=lower_bound(v2+1,v2+1+n,b[i].y)-v2;
int r=upper_bound(v2+1,v2+1+n,b[i].y+d)-v2-1;
Change(rt1,1,n,l,r,b[i].id);
if(!b[i].y)q.push(b[i].id),f[b[i].id]=0,vis[b[i].id]=1;
}
for(int i=1;i<=n;i++){
int l=lower_bound(v1+1,v1+1+n,g[i].x)-v1;
int r=upper_bound(v1+1,v1+1+n,g[i].x+d)-v1-1;
Change(rt0,1,n,l,r,g[i].id);
if(!g[i].x)q.push(g[i].id),f[g[i].id]=0,vis[g[i].id]=1;
}
SPFA();
for(int i=1;i<=n;i++){
if(f[i]>2147483647/3)printf("-1\n");
else printf("%d\n",f[i]+1);
}
}