P4083-[USACO17DEC]A Pie for a Pie G【线段树,最短路】

正题

题目链接: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的礼物开始跑,之后直接输出每个礼物的最短路即可


c o d e code code

#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);
	}
}

你可能感兴趣的:(图论,数据结构)