[DS记录]AT2160 [ARC065C] へんなコンパス / Manhattan Compass

command_block

2021-05-17 09:09:46

Personal

**题意** : (这翻译都是些啥,看不懂 qwq) 给出平面上的 $n$ 个点。 记点 $p_i,p_j$ 之间的曼哈顿距离为 $d(i,j)=|x_i-x_j|+|y_i-y_j|$。 有两个人(不区分),初始时分别在点 $p_a,p_b$。 当两人在点 $u,v$ 时,若存在点 $t$ 满足 $d(u,v)=d(u,t)$ ,则在 $v$ 的人可以移动到 $t$。 求两人能达到的不同状态(位置无序对)总数。 $n\leq 10^5$ ,时限$\texttt{3s}$。 ------------ 记 $L=d(p_a,p_b)$ ,不难发现,在旅途中 $d(u,v)$ 是不会变化的,一直为 $L$。 若某个人能到达点 $u$ ,则对于所有 $d(u,v)=L$ 的 $v$ ,无序对 $(u,v)$ 都是可达的。 于是,只需判定每个点能否被到达。 对于某个已经被到达的点 $u$,检查所有 $d(u,v)=L$ 的 $v$ ,把他们也更新为可达点。 这可以用队列实现,并用 `std::set` 维护点(转切比雪夫距离更方便)。 每个点只会被删除一次,故复杂度为 $O(n\log n)$。 写起来没啥难点,就是有点啰嗦。 ```cpp #include<algorithm> #include<cstdio> #include<vector> #include<queue> #include<set> #define Pr pair<int,int> #define fir first #define sec second #define mp make_pair #define pb push_back #define ll long long #define itor set<Pr>::iterator #define MaxN 100500 using namespace std; const int INF=2000000100; int abs(int x){return (x<0) ? -x : x;} set<Pr> sx[MaxN],sy[MaxN]; vector<int> tx[MaxN],ty[MaxN]; int n,x[MaxN],y[MaxN],ax[MaxN],ay[MaxN],d[MaxN]; bool vis[MaxN]; queue<int> q; void del(itor itl,itor itr,set<Pr> &s){ for (itor sav;itl!=itr;){ q.push(itl->sec); sav=itl;itl++; s.erase(sav); } } int main() { int u,v; scanf("%d%d%d",&n,&u,&v); for (int i=1,x0,y0;i<=n;i++){ scanf("%d%d",&x0,&y0); ax[i]=x[i]=x0-y0; ay[i]=y[i]=x0+y0; }sort(ax+1,ax+n+1);sort(ay+1,ay+n+1); for (int i=1;i<=n;i++){ int x0=lower_bound(ax+1,ax+n+1,x[i])-ax ,y0=lower_bound(ay+1,ay+n+1,y[i])-ay; tx[x0].pb(y[i]);ty[y0].pb(x[i]); sx[x0].insert(mp(y[i],i));sy[y0].insert(mp(x[i],i)); } for (int i=1;i<=n;i++){ sort(tx[i].begin(),tx[i].end()); sort(ty[i].begin(),ty[i].end()); } int L=max(abs(x[u]-x[v]),abs(y[u]-y[v])); for (int i=1,l,r;i<=n;i++){ if ((ll)x[i]-L>-INF){ int to=lower_bound(ax+1,ax+n+1,x[i]-L)-ax; if (ax[to]==x[i]-L){ l=lower_bound(tx[to].begin(),tx[to].end(),max(-INF,y[i]-L))-tx[to].begin(); r=upper_bound(tx[to].begin(),tx[to].end(),min(INF,y[i]+L))-tx[to].begin(); d[i]+=r-l; } } if ((ll)x[i]+L<INF){ int to=lower_bound(ax+1,ax+n+1,x[i]+L)-ax; if (ax[to]==x[i]+L){ l=lower_bound(tx[to].begin(),tx[to].end(),max(-INF,y[i]-L))-tx[to].begin(); r=upper_bound(tx[to].begin(),tx[to].end(),min(INF,y[i]+L))-tx[to].begin(); d[i]+=r-l; } } if ((ll)y[i]-L>-INF){ int to=lower_bound(ay+1,ay+n+1,y[i]-L)-ay; if (ay[to]==y[i]-L){ l=lower_bound(ty[to].begin(),ty[to].end(),max(-INF,x[i]-L+1))-ty[to].begin(); r=upper_bound(ty[to].begin(),ty[to].end(),min(INF,x[i]+L-1))-ty[to].begin(); d[i]+=r-l; } } if ((ll)y[i]+L<INF){ int to=lower_bound(ay+1,ay+n+1,y[i]+L)-ay; if (ay[to]==y[i]+L){ l=lower_bound(ty[to].begin(),ty[to].end(),max(-INF,x[i]-L+1))-ty[to].begin(); r=upper_bound(ty[to].begin(),ty[to].end(),min(INF,x[i]+L-1))-ty[to].begin(); d[i]+=r-l; } } } q.push(u);q.push(v); while(!q.empty()){ int u=q.front();q.pop(); if (vis[u])continue; vis[u]=1; itor itl,itr; if ((ll)x[u]-L>-INF){ int to=lower_bound(ax+1,ax+n+1,x[u]-L)-ax; if (ax[to]==x[u]-L){ itl=sx[to].lower_bound(mp(max(-INF,y[u]-L),0)); itr=sx[to].upper_bound(mp(min(INF,y[u]+L),INF)); del(itl,itr,sx[to]); } } if ((ll)x[u]+L<INF){ int to=lower_bound(ax+1,ax+n+1,x[u]+L)-ax; if (ax[to]==x[u]+L){ itl=sx[to].lower_bound(mp(max(-INF,y[u]-L),0)); itr=sx[to].upper_bound(mp(min(INF,y[u]+L),INF)); del(itl,itr,sx[to]); } } if ((ll)y[u]-L>-INF){ int to=lower_bound(ay+1,ay+n+1,y[u]-L)-ay; if (ay[to]==y[u]-L){ itl=sy[to].lower_bound(mp(max(-INF,x[u]-L),0)); itr=sy[to].upper_bound(mp(min(INF,x[u]+L),INF)); del(itl,itr,sy[to]); } } if ((ll)y[u]+L<INF){ int to=lower_bound(ay+1,ay+n+1,y[u]+L)-ay; if (ay[to]==y[u]+L){ itl=sy[to].lower_bound(mp(max(-INF,x[u]-L),0)); itr=sy[to].upper_bound(mp(min(INF,x[u]+L),INF)); del(itl,itr,sy[to]); } } } ll ans=0; for (int i=1;i<=n;i++) if (vis[i])ans+=d[i]; printf("%lld",ans/2); return 0; } ```