正题
题目链接:https://www.luogu.com.cn/problem/P4083
题目大意
开始时AAA和BBB各有两个礼物,每个礼物对两个人有不同的价值,开始时AAA会送BBB一个礼物。
对于一个收到礼物的人,如果该礼物对他来说价值为valvalval,那么他会回送一个对于他来说[val,val+d][val,val+d][val,val+d]这个范围内的礼物。
直到某个人收到价值为000的礼物就停止,求对于AAA开始送的每个礼物,最少要互送多少个礼物才能停止
解题思路
我们可以发现其实就是每次对于一个区间内连边然后求最短路。
我们对于AAA和BBB各自开一棵线段树然后优化一下连边,从价值为000的礼物开始跑,之后直接输出每个礼物的最短路即可
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
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);}
}