四校联考 推冰块
2<=n,m<=10^9,0<=k<=50000。
我们发现有用的格子不是很多,经过详细的分类讨论,只有这些格子是有用的:
四个角,以及障碍物(或减速带)本身和上下左右四个方向,以及障碍物所在行列(及±1的)的头尾两个。
那么我们只要把所有 障碍 和 减速带 按x-y和y-x排序一下,对于每一个有用的格子二分一下找到往左和往右会推到哪里,连边完暴力bfs即可。
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <string> #include <bitset> #include <vector> #include <set> #include <map> #include <queue> #include <algorithm> #include <sstream> #include <stack> #include <iomanip> using namespace std; #define pb push_back #define mp make_pair typedef pair<int,int> pii; typedef long long ll; typedef double ld; typedef vector<int> vi; #define fi first #define se second #define fe first #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);} #define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);} #define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);} #define es(x,e) (int e=fst[x];e;e=nxt[e]) #define VIZ {printf("digraph G{\n"); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;\n",i,vb[e]); puts("}");} #ifdef LOCAL #define TIMER cerr<<clock()<<"ms\n" #else #define TIMER #endif #define SZ 1234567 int n,m,k,N=0; int xs[SZ],ys[SZ],ts[SZ]; typedef pair<int,int> pii; map<pii,int> sta; bool cmp2(pii a,pii b) { if(a.se!=b.se) return a.se<b.se; return a.fi<b.fi; } pii ps[SZ]; int pn=0; pii ss[SZ],rs[SZ]; int dx[4]={1,-1,0,0},dy[4]={0,0,-1,1}; void rec(int a,int b) { if(sta[pii(a,b)]==1) return; if(a<1||b<1||a>n||b>m) return; ps[++pn]=pii(a,b); } int ls(pii a) {return lower_bound(ps+1,ps+1+pn,a)-ps;} int S,T; int qs[SZ]; int dist[SZ]; #undef SZ #define SZ 1234567 Edg void conn(pii a,pii b) { if(a==b) return; ad_de(ls(a),ls(b)); } void spfa() { int h=0,t=0; qs[t++]=S; dist[S]=1; while(h^t) { int x=qs[h++]; for es(x,e) { int b=vb[e]; if(dist[b]) continue; dist[b]=dist[x]+1; qs[t++]=b; } } } int main() { FO(ice) scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=k;i++) { scanf("%d%d%d",xs+i,ys+i,ts+i); sta[pii(xs[i],ys[i])]=ts[i]+1; } rec(1,1); rec(n,m); rec(1,m); rec(n,1); for(int i=1;i<=k;i++) { rec(xs[i],1); rec(xs[i],m); rec(1,ys[i]); rec(n,ys[i]); rec(xs[i]+1,1); rec(xs[i]+1,m); rec(xs[i]-1,1); rec(xs[i]-1,m); rec(1,ys[i]+1); rec(n,ys[i]+1); rec(1,ys[i]-1); rec(n,ys[i]-1); rec(xs[i],ys[i]); for(int j=0;j<4;j++) rec(xs[i]+dx[j],ys[i]+dy[j]); } sort(ps+1,ps+1+pn); pn=unique(ps+1,ps+1+pn)-ps-1; int sn=0,rn=0; for(int i=1;i<=k;i++) { if(ts[i]==0) ss[++sn]=pii(xs[i],ys[i]); else rs[++rn]=pii(xs[i],ys[i]); } ss[++sn]=pii(-2000000000,-2000000000); ss[++sn]=pii(2000000000,2000000000); rs[++rn]=pii(-2000000000,-2000000000); rs[++rn]=pii(2000000000,2000000000); sort(ss+1,ss+1+sn); sort(rs+1,rs+1+rn); //先处理左右 for(int i=1;i<=pn;i++) { int x=ps[i].fi,y=ps[i].se; pii cur=pii(x,y); if(y!=1) //L { int maxn=1; int id=lower_bound(rs+1,rs+1+rn,cur)-rs-1; pii ns=rs[id]; if(ns.fi==x) maxn=max(maxn,ns.se); id=lower_bound(ss+1,ss+1+sn,cur)-ss-1; ns=ss[id]; if(ns.fi==x) maxn=max(maxn,ns.se+1); conn(cur,pii(x,maxn)); } if(y!=m) //R { int minn=m; int id=upper_bound(rs+1,rs+1+rn,cur)-rs; pii ns=rs[id]; if(ns.fi==x) minn=min(minn,ns.se); id=upper_bound(ss+1,ss+1+sn,cur)-ss; ns=ss[id]; if(ns.fi==x) minn=min(minn,ns.se-1); conn(cur,pii(x,minn)); } } sort(ss+1,ss+1+sn,cmp2); sort(rs+1,rs+1+rn,cmp2); for(int i=1;i<=pn;i++) { int x=ps[i].fi,y=ps[i].se; pii cur=pii(x,y); if(x!=1) //U { int maxn=1; int id=lower_bound(rs+1,rs+1+rn,cur,cmp2)-rs-1; pii ns=rs[id]; if(ns.se==y) maxn=max(maxn,ns.fi); id=lower_bound(ss+1,ss+1+sn,cur,cmp2)-ss-1; ns=ss[id]; if(ns.se==y) maxn=max(maxn,ns.fi+1); conn(cur,pii(maxn,y)); } if(x!=n) //R { int minn=n; int id=upper_bound(rs+1,rs+1+rn,cur,cmp2)-rs; pii ns=rs[id]; if(ns.se==y) minn=min(minn,ns.fi); id=upper_bound(ss+1,ss+1+sn,cur,cmp2)-ss; ns=ss[id]; if(ns.se==y) minn=min(minn,ns.fi-1); conn(cur,pii(minn,y)); } } S=ls(pii(1,1));T=ls(pii(n,m)); spfa(); cout<<dist[T]-1<<"\n"; }