社区讨论

19pts,悬4关

P6007[USACO20JAN] Springboards G参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mm33yj7p
此快照首次捕获于
2026/02/26 14:54
2 周前
此快照最后确认于
2026/02/27 19:55
2 周前
查看原帖
CPP
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int inf=0x7fffffff;
const int N=2e5;
int n,p;
struct node
{
	int x,y;
	int pos;
	int id;
	int step;
}num[N+5];
bool cmp1(node xx,node yy)
{
	if(xx.x==yy.x)
		return xx.y<yy.y;
	return xx.x<yy.x;
}
bool cmp2(node xx,node yy){return xx.y<yy.y;}
int jl(int xx1,int yy1,int xx2,int yy2){return abs(xx1-xx2)+abs(yy1-yy2);}
void cdq(int l,int r)
{
	if(l==r) return ;
	int mid=(l+r)>>1;
	cdq(l,mid);
	sort(num+l,num+mid+1,cmp2);
	sort(num+mid+1,num+r+1,cmp2);
	int i=l,j=mid+1;
	int minn=inf;
	while(j<=r)
	{
		while(i<=mid && num[i].y<=num[j].y)
		{
			if(num[j].pos==1 && num[i].pos==2)
				minn=min(minn,num[i].step+jl(num[i].x,num[i].y,num[j].x,num[j].y));
			if((num[j].pos==2 && num[i].pos==1))
				if(num[j].id==num[i].id || num[i].id==-1)
					minn=min(minn,num[i].step);
			i++;
		}
		num[j].step=minn;
		if(num[j].id==-1) num[j].step=0;
		j++;
	}
	cdq(mid+1,r);
	return ;
}
signed main()
{
	cin>>n>>p;
	for(int i=1;i<=p;i++)
	{
		int xx1,yy1,xx2,yy2;
		cin>>xx1>>yy1>>xx2>>yy2;
		num[i*2-1]={xx1,yy1,1,i,inf};
		num[i*2]={xx2,yy2,2,i,inf};
	}
	num[2*p+1]={0,0,2,-1,0};
	num[2*p+2]={n,n,1,-2,0};
	sort(num+1,num+2*p+3,cmp1);
	cdq(1,2*p+2);
	cout<<num[2*p+2].step<<"\n";
	return 0;
}
可以证明最长的跳跃距离就是最优方案。
所以只需要考虑特殊点(跳板和(0,0),(N,N))。
考虑把跳板分为起点和终点,在保证偏序关系的情况下,每个起点的答案需要从另一个终点转移而来,终点的答案从对应的起点转移而来。发现(0,0)满足终点的性质,(N,N)满足起点的性质。
把这些点都加入同一个序列,跑一个cdq分治。

回复

0 条回复,欢迎继续交流。

正在加载回复...