BZOJ 2304: [Apio2011]寻路

好久不写题解了不劲啊

最近被多校虐哭了

无聊来水一水APIO的题

感觉APIO的题黑科技不是很多啊

这题大概不是lower_bound和upper_bound的应用?

反正用这两个函数就可以找到每个点四个方向可以到的点了,然后把新找到的这个点加到它所在的矩形的那个线段上去,最后对于每条线段处理一下上面的点

跑跑spfa就过了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const ll inf=1LL<<50;
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
#define mmt(a,v) memset(a,v,sizeof(a))
#define tra(i,u) for(int i=head[u];i;i=e[i].next)
const int N=1000+5;
const int M=12000+5;
struct Edge{int to,next,v;}e[N*N];
int head[M],cnt;
void ins(int u,int v,int w){e[++cnt]=(Edge){v,head[u],w};head[u]=cnt;}
void insert(int u,int v,int w){ins(u,v,w);ins(v,u,w);}
ll d[M];
bool inq[M];
void spfa(int s){
	memset(d,0x3f,sizeof(d));queue<int>q;q.push(s);d[s]=0;
	while(!q.empty()){
		int u=q.front();q.pop();inq[u]=0;
		tra(i,u){
			int v=e[i].to;
			if(d[v]>d[u]+e[i].v){
				d[v]=d[u]+e[i].v;
				if(!inq[v])inq[v]=1,q.push(v);
			}
		}
	}
}
struct point{
	int x,y;
	point(){}
	point(int x,int y):x(x),y(y){}
	void print(){printf("%d %d\n",x,y);}
	bool operator == (const point &p)const{
		return x==p.x&&y==p.y;
	}
}p[M];
struct col{
	int d,u,x;
	vector<int>s;
	col(){}
	col(int d,int u,int x):d(d),u(u),x(x){s.clear();}
	bool operator < (const col &c)const{
		return x<c.x;
	}
}c[N<<1];
struct row{
	int l,r,y;
	vector<int>s;
	row(){}
	row(int l,int r,int y):l(l),r(r),y(y){s.clear();}
	bool operator < (const row &x)const{
		return y<x.y;
	}
}r[N<<1];
bool cmp(int i,int j){
	return p[i].x==p[j].x?p[i].y<p[j].y:p[i].x<p[j].x;
}
int iabs(int x){return max(x,-x);}
int dist(point p1,point p2){return iabs(p1.x-p2.x)+iabs(p1.y-p2.y);}
int main(){
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	int T;scanf("%d",&T);
	while(T--){
		scanf("%d%d%d%d",&p[1].x,&p[1].y,&p[2].x,&p[2].y);
		int n;scanf("%d",&n);
		mmt(head,0);cnt=0;
		int pn=2,sn=0;
		c[++sn]=col(1,1,p[1].x);r[sn]=row(1,1,p[1].y);
		c[++sn]=col(2,2,p[2].x);r[sn]=row(2,2,p[2].y);
		rep(i,1,n){
			static int x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
			if(x1>x2)swap(x1,x2);if(y1>y2)swap(y1,y2);
			p[++pn]=point(x1,y1);p[++pn]=point(x1,y2);
			p[++pn]=point(x2,y1);p[++pn]=point(x2,y2);
			c[++sn]=col(pn-3,pn-2,x1);r[sn]=row(pn-3,pn-1,y1);
			c[++sn]=col(pn-1,pn,x2);r[sn]=row(pn-2,pn,y2);
		}
		sort(c+1,c+1+sn);sort(r+1,r+1+sn);
		int sz=pn;
		rep(i,1,sz){
			static int j,id;
			static point np;
			j=upper_bound(c+1,c+1+sn,col(0,0,p[i].x))-c;
			while(j<=sn){
				if(p[c[j].d].y<=p[i].y&&p[i].y<=p[c[j].u].y){
					np=point(c[j].x,p[i].y);
					if(np==p[c[j].d])id=c[j].d;
					else if(np==p[c[j].u])id=c[j].u;
					else id=++pn,p[pn]=np;
					insert(i,id,dist(np,p[i]));
					c[j].s.push_back(id);
					break;
				}
				j++;
			}
			j=lower_bound(c+1,c+1+sn,col(0,0,p[i].x))-c-1;
			while(j>=1){
				if(p[c[j].d].y<=p[i].y&&p[i].y<=p[c[j].u].y){
					np=point(c[j].x,p[i].y);
					if(np==p[c[j].d])id=c[j].d;
					else if(np==p[c[j].u])id=c[j].u;
					else id=++pn,p[pn]=np;
					insert(i,id,dist(np,p[i]));
					c[j].s.push_back(id);
					break;
				}
				j--;
			}
			j=upper_bound(r+1,r+1+sn,row(0,0,p[i].y))-r;
			while(j<=sn){
				if(p[r[j].l].x<=p[i].x&&p[i].x<=p[r[j].r].x){
					np=point(p[i].x,r[j].y);
					if(np==p[r[j].l])id=r[j].l;
					else if(np==p[r[j].r])id=r[j].r;
					else id=++pn,p[pn]=np;
					insert(i,id,dist(np,p[i]));
					r[j].s.push_back(id);
					break;
				}
				j++;
			}
			j=lower_bound(r+1,r+1+sn,row(0,0,p[i].y))-r-1;
			while(j>=1){
				if(p[r[j].l].x<=p[i].x&&p[i].x<=p[r[j].r].x){
					np=point(p[i].x,r[j].y);
					if(np==p[r[j].l])id=r[j].l;
					else if(np==p[r[j].r])id=r[j].r;
					else id=++pn,p[pn]=np;
					insert(i,id,dist(np,p[i]));
					r[j].s.push_back(id);
					break;
				}
				j--;
			}
		}
		rep(i,1,sn){
			sort(c[i].s.begin(),c[i].s.end(),cmp);
			sort(r[i].s.begin(),r[i].s.end(),cmp);
			rep(j,1,(int)c[i].s.size()-1)
			insert(c[i].s[j-1],c[i].s[j],dist(p[c[i].s[j-1]],p[c[i].s[j]]));
			rep(j,1,(int)r[i].s.size()-1)
			insert(r[i].s[j-1],r[i].s[j],dist(p[r[i].s[j-1]],p[r[i].s[j]]));
		}
		spfa(1);
		if(d[2]>=inf)puts("No Path");
		else printf("%lld\n",d[2]);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值