1. 程式人生 > >[主席樹優化建圖] LOJ#546. 「LibreOJ β Round #7」網格圖

[主席樹優化建圖] LOJ#546. 「LibreOJ β Round #7」網格圖

最簡單的思路是離散化後 O(k2)

然而對於橫著的朝向,極長的橫著相連的格子的答案是相同的,豎著的同理

那麼把極長的相連的格子也縮起來,用主席樹優化建圖,就可以 O(klogk) 最短路了

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#define fi first
#define se second

using namespace std;

typedef
pair<int,int> pii; const int N=50010; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(); x=0; for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10
+c-'0',c=nc()); } struct Line{ int l,r,g; Line(){} Line(int _l,int _r,int _g):l(_l),r(_r),g(_g){} friend bool operator <(Line a,Line b){ return a.l<b.l; } }; int n,m,k,q,dis[N*200]; vector<int> h,s,hp[N<<2],sp[N<<2]; int x[N],y[N],sx,sy; vector<Line> hl[N<<2
],sl[N<<2]; vector<pii> ad[N<<2],de[N<<2]; int rt,ls[N*200],rs[N*200],ccnt; int G[N*200],cnt; struct edge{ int t,nx,w; }E[N*400]; inline void addedge(int x,int y,int w){ //cerr<<'\t'<<x<<' '<<y<<' '<<w<<endl; E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt; E[cnt].w=w; } void add(int &g,int x,int l,int r,int y){ int k=g; g=++ccnt; ls[g]=ls[k]; rs[g]=rs[k]; if(l==r) return addedge(g,y,1); int mid=l+r>>1; if(x<=mid) add(ls[g],x,l,mid,y); else add(rs[g],x,mid+1,r,y); if(ls[g]) addedge(g,ls[g],0); if(rs[g]) addedge(g,rs[g],0); } void link(int g,int l,int r,int L,int R,int y){ if(!g) return ; if(l==L && R==r){ addedge(y,g,0); return ; } int mid=L+R>>1; if(r<=mid) link(ls[g],l,r,L,mid,y); else if(l>mid) link(rs[g],l,r,mid+1,R,y); else link(ls[g],l,mid,L,mid,y),link(rs[g],mid+1,r,mid+1,R,y); } queue<int> Q; int vis[N*200]; int main(){ freopen("1.in","r",stdin); freopen("1.out","w",stdout); read(n); read(m); read(k); read(q); for(int i=1;i<=k;i++){ read(x[i]); read(y[i]); h.push_back(x[i]); if(x[i]>1) h.push_back(x[i]-1); if(x[i]<n) h.push_back(x[i]+1); s.push_back(y[i]); if(y[i]>1) s.push_back(y[i]-1); if(y[i]<m) s.push_back(y[i]+1); } read(sx); read(sy); h.push_back(sx); s.push_back(sy); if(sx>1) h.push_back(sx-1); if(sx<n) h.push_back(sx+1); if(sy>1) s.push_back(sy-1); if(sy<m) s.push_back(sy+1); h.push_back(n); s.push_back(m); sort(h.begin(),h.end()); sort(s.begin(),s.end()); h.resize(unique(h.begin(),h.end())-h.begin()); s.resize(unique(s.begin(),s.end())-s.begin()); for(int i=1;i<=k;i++){ x[i]=lower_bound(h.begin(),h.end(),x[i])-h.begin(); y[i]=lower_bound(s.begin(),s.end(),y[i])-s.begin(); hp[x[i]].push_back(y[i]); sp[y[i]].push_back(x[i]); } n=lower_bound(h.begin(),h.end(),n)-h.begin(); m=lower_bound(s.begin(),s.end(),m)-s.begin(); for(int i=0;i<h.size();i++){ sort(hp[i].begin(),hp[i].end()); int lst=-1; for(int j=0;j<hp[i].size();j++){ if(lst+1<hp[i][j]) hl[i].push_back(Line(lst+1,hp[i][j]-1,++ccnt)); lst=hp[i][j]; } if(lst+1<=m) hl[i].push_back(Line(lst+1,m,++ccnt)); } for(int i=0;i<s.size();i++){ sort(sp[i].begin(),sp[i].end()); int lst=-1; for(int j=0;j<sp[i].size();j++){ if(lst+1<sp[i][j]) sl[i].push_back(Line(lst+1,sp[i][j]-1,++ccnt)); lst=sp[i][j]; } if(lst+1<=n) sl[i].push_back(Line(lst+1,n,++ccnt)); } for(int i=0;i<s.size();i++){ for(int j=0;j<sl[i].size();j++) ad[sl[i][j].l].push_back(pii(i,sl[i][j].g)); } for(int i=0;i<h.size();i++){ for(int j=0;j<ad[i].size();j++) add(rt,ad[i][j].fi,0,s.size()-1,ad[i][j].se); for(int j=0;j<hl[i].size();j++) link(rt,hl[i][j].l,hl[i][j].r,0,s.size()-1,hl[i][j].g); ad[i].clear(); } rt=0; for(int i=0;i<h.size();i++) for(int j=0;j<hl[i].size();j++) ad[hl[i][j].l].push_back(pii(i,hl[i][j].g)); for(int i=0;i<s.size();i++){ for(int j=0;j<ad[i].size();j++) add(rt,ad[i][j].fi,0,h.size()-1,ad[i][j].se); for(int j=0;j<sl[i].size();j++) link(rt,sl[i][j].l,sl[i][j].r,0,h.size()-1,sl[i][j].g); } sx=lower_bound(h.begin(),h.end(),sx)-h.begin(); sy=lower_bound(s.begin(),s.end(),sy)-s.begin(); int S1=hl[sx][upper_bound(hl[sx].begin(),hl[sx].end(),Line(sy,0,0))-hl[sx].begin()-1].g; int S2=sl[sy][upper_bound(sl[sy].begin(),sl[sy].end(),Line(sx,0,0))-sl[sy].begin()-1].g; for(int i=1;i<=ccnt;i++) dis[i]=1<<29; dis[S1]=dis[S2]=0; Q.push(S1); Q.push(S2); vis[S1]=vis[S2]=1; while(!Q.empty()){ int x=Q.front(); Q.pop(); vis[x]=0; for(int i=G[x];i;i=E[i].nx) if(dis[E[i].t]>dis[x]+E[i].w){ dis[E[i].t]=dis[x]+E[i].w; if(!vis[E[i].t]) vis[E[i].t]=1,Q.push(E[i].t); } } while(q--){ int x,y; read(x); read(y); x=lower_bound(h.begin(),h.end(),x)-h.begin(); y=lower_bound(s.begin(),s.end(),y)-s.begin(); int T1=upper_bound(hl[x].begin(),hl[x].end(),Line(y,0,0))-hl[x].begin()-1; int T2=upper_bound(sl[y].begin(),sl[y].end(),Line(x,0,0))-sl[y].begin()-1; T1=hl[x][T1].g; T2=sl[y][T2].g; int ans=min(dis[T1],dis[T2]); if(ans==(1<<29)) ans=-1; printf("%d\n",ans); } return 0; }