平面上有$N$个点$(X_i\space, Y_i)$,定义$D(a,b)=|X_a-X_b|+|Y_a-Y_b|$。

如果你当前在$(p,q)$,这个无序二元组(即$(p,q)$和$(q,p)$被认为是相同的),并且存在$r$使得$D(p, q)=D(p, r)$,那么你就可以到达$(p, r)$这个无序二元组。

一开始你在$(a,b)$,这个无序二元组,求你能到达多少不同的无序二元组。

题解

这道题其实没有任何大的思维跨越,大体思想就是先求出$(a,b)$的曼哈顿距离,然后$bfs$看可以连出去多少条边即可。

然而这样朴素的做法是$O(N^2)$的,想办法优化这一过程。

显然枚举出发点不能进行深一步的优化,所以我们考虑优化枚举到达点的方法。

不难发现,从固定曼哈顿距离确定每一个点出发到达的点一定在一个斜$45$度的正方形上,可以对于每一条正反斜$45$度的直线开一个$vector$按$x$升序存下内部的点,这样就可以在$vector$上进行二分。

至于如何将这些点依次加入队列,可以直接开一个并查集维护$vector$中右侧最近的没有被删除的点,由于每个点只会被删除一次,所以总复杂度$O(N)$

考虑到每次在$vector$上找点还需要二分,所以常数较大,但复杂度仍是$O(N\log N)$

#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<map>
#define LL long long
#define M 100020
using namespace std;
int read(){
int nm=0,fh=1; char cw=getchar();
for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
return nm*fh;
}
int n,m,cnt,A,B,q[M],hd,tl,D,X[M],Y[M];
LL ans;
bool vis[M];
vector<int> t[M<<1],f[M<<1];
map<int,int> ID1,ID2;
int fd(int kd,int x){return f[kd][x]==x?x:f[kd][x]=fd(kd,f[kd][x]);}
bool cmp(int x,int y){return X[x]<X[y];}
void gtin(int x){
int tar; X[x]=read(),Y[x]=read();
if(ID1.count(X[x]+Y[x])) tar=ID1[X[x]+Y[x]];
else cnt++,tar=ID1[X[x]+Y[x]]=cnt,f[tar].push_back(0);
t[tar].push_back(x),f[tar].push_back(f[tar].size());
if(ID2.count(X[x]-Y[x])) tar=ID2[X[x]-Y[x]];
else cnt++,tar=ID2[X[x]-Y[x]]=cnt,f[tar].push_back(0);
t[tar].push_back(x),f[tar].push_back(f[tar].size());
}
int getpos(int kd,int minx){
int l=0,r=t[kd].size(),fin=0,md;
while(l<=r){
md=((l+r)>>1);
if(md<t[kd].size()&&X[t[kd][md]]<minx) l=md+1;
else fin=md,r=md-1;
} return fin;
}
void del(int x){
vis[x]=true; q[tl++]=x;
int kd=ID1[X[x]+Y[x]],fin; fin=getpos(kd,X[x]);
f[kd][fin]=fd(kd,fin+1),kd=ID2[X[x]-Y[x]];
fin=getpos(kd,X[x]),f[kd][fin]=fd(kd,fin+1);
}
void calc(int kd,int lx,int rx,bool down){
int t1=getpos(kd,lx),t2=getpos(kd,rx),tot=t[kd].size();
if(down&&t1<tot&&X[t[kd][t1]]<=lx) t1++;
if(down&&t2<tot&&X[t[kd][t2]]<=rx) t2++; ans+=t2-t1;
for(t1=fd(kd,t1);t1<t2&&t1<tot;t1=fd(kd,t1+1)) del(t[kd][t1]); }
void getans(int x){
if(ID2.count(X[x]-Y[x]-D)) calc(ID2[X[x]-Y[x]-D],X[x]-D,X[x],false);
if(ID1.count(X[x]+Y[x]+D)) calc(ID1[X[x]+Y[x]+D],X[x],X[x]+D,false);
if(ID1.count(X[x]+Y[x]-D)) calc(ID1[X[x]+Y[x]-D],X[x]-D,X[x],true);
if(ID2.count(X[x]-Y[x]+D)) calc(ID2[X[x]-Y[x]+D],X[x],X[x]+D,true);
}
void solve(){
del(A),del(B),D=abs(X[A]-X[B])+abs(Y[A]-Y[B]);
while(hd<tl){int now=q[hd++];getans(now);}
}
int main(){
n=read(),A=read(),B=read();
for(int i=1;i<=n;i++) gtin(i);
for(int i=1;i<=cnt;i++) sort(t[i].begin(),t[i].end(),cmp);
solve(),printf("%lld\n",ans/2); return 0;
}

  

Arc065_E Manhattan Compass的更多相关文章

  1. [arc065E]Manhattan Compass[曼哈顿距离和切比雪夫距离转换]

    Description 传送门 Solution 题目要求的是曼达顿距离,对于每个点(x,y),我们把它变为(x-y,x+y),就可以转换成求切比雪夫距离了. 证明如下:$max(\left | (x ...

  2. AT2160 へんなコンパス / Manhattan Compass

    传送门 乍一看像是一个计算几何,然后想到了BFS,但是苦于无奈\(O(n^2)\)不会优化 然后以下参考zjq_shadow大佬的思路 显然发现曼哈顿距离很麻烦,除了暴力枚举貌似没什么很好的办法 考虑 ...

  3. AtCoder 瞎做

    目录 ARC 058 E - 和風いろはちゃん / Iroha and Haiku 题意 题解 技巧 代码 ARC 059 F - バイナリハック / Unhappy Hacking 题意 题解 技巧 ...

  4. NOIp2018模拟赛三十八

    爆〇啦~ A题C题不会写,B题头铁写正解: 随手过拍很自信,出分一看挂成零. 若要问我为什么?gtmdsubtask! 神tm就一个subtask要么0分要么100,结果我预处理少了一点当场去世 难受 ...

  5. 【AtCoder】ARC065

    ARC065 C - 白昼夢 / Daydream 直接递推就好 #include <bits/stdc++.h> #define fi first #define se second # ...

  6. Sass之坑Compass编译报错

    前段时间在使用Compass时遇到了其为难处理的一个坑,现记录到博客希望能帮助到各位. 一.问题: 利用Koala或者是gulp编译提示如下,截图为koala编译提示错误: 二.解决办法 从问题截图上 ...

  7. compass reset和layout [Sass和compass学习笔记]

    reset 可以重置浏览器的的html的默认样式,因为各个浏览器对有些元素解析差别很大 通过重置样式可以让样式的浏览器兼容 更简单 使用方法简单 @import "compass/reset ...

  8. 分享15款很实用的 Sass 和 Compass 工具

    Sass 是 CSS 的扩展,增加了嵌套规则,变量,混入功能等很多更多.它简化了组织和维护 CSS 代码的成本.Compass 是一个开源的 CSS 框架,使得使用 CSS3 和流行的设计模式比以往任 ...

  9. SASS+COMPASS 自适应 学习笔记

    来源 http://snugug.github.io/RWD-with-Sass-Compass/#/ 1 安装 COMPASS 扩展 安装 方式 gem 'extension', '~>X.Y ...

随机推荐

  1. Linux删除乱码文件的方法

    当文件名为乱码的时候,无法通过键盘输入文件名,所以在终端下就不能直接利用rm,mv等命令管理文件了. 我们可以通过以下几种方法删除linux下的乱码文件.(文件名为乱码) l  方法1 我们知道每个文 ...

  2. PHP新手必学之刚进公司装环境

    由于今天去一家公司做项目,又重新的装了一遍所熟悉的PHP环境,所以记录下来,总结下. PHP环境主要: PHPstudy(apache+mysql+php)+phpstorm+navicate 解释: ...

  3. 走进EC6的let和const命令

    详细学习链接: http://es6.ruanyifeng.com/#docs/let let命令 基本用法 ES6新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命 ...

  4. Apache启动失败(Windows 无法在本地计算机启动Apache2.2)

    该问题产生的原因有很多,这里就说说我遇到的问题: 这个问题是突然遇到的,启动的时候连日志都没有产生,最后是通过window的日志中发现问题所在的,如图所示: 发现是目录错了.其他问题也可以通过该日志找 ...

  5. maven-tomcat7;IOC;AOP;数据库远程连接

    [说明]真的是好烦下载插件啊,maven-tomcat7 插件试了好多次都不行,下载不成:部署不成:好不容易从github中得到的springmvc项目也是运行不起来,中间又是查了许多东西,绕着绕着都 ...

  6. WiX 中XML引用变量说明

    WiX 安装工程中的XML 文件所引用变量说明: The WiX project supports the following project reference variables: Variabl ...

  7. Apache Shiro 使用手册(三)Shiro 授权(转发:http://kdboy.iteye.com/blog/1155450)

    授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限. 如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限,以及是否拥有打印的权限等等. 一.授权的三要素 授权有着三 ...

  8. GPS模块坐标偏差很大?

    回答这个问题,首先要了解几个概念: 火星坐标系:天朝有关部门规定,为了保证国家安全,所有的地图公司提供的地图必须对实际的GPS坐标进行一定的偏移,偏移后的GPS坐标系俗称火星坐标系,而这个偏移是不固定 ...

  9. linux删除文件夹的命令

    使用rm -rf 目录名字 命令即可 -r 就是向下递归,不管有多少级目录,一并删除-f 就是直接强行删除,不作任何提示的意思 eg 删除文件夹实例:rm -rf /var/log/httpd/acc ...

  10. spring-cloud 实现更新配置不用重启服务 @FreshScope

    继续前面搭建的spring cloud. 这里是基于rabbitMQ搭建的,首先需要在电脑上安装rabbitMQ. 在client端和server端分别加上如下依赖 compile group: 'o ...