好久不写题解了不劲啊
最近被多校虐哭了
无聊来水一水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; }