ARC065C
曼哈顿距离和切比雪夫距离,一般出现了其中一个就要去想想是不是可以转换成另一个。
本题就是一个典型的例子,在曼哈顿距离下会比较麻烦——每次可以转移到的点都是一个斜着的正方形,不方便枚举。
而转换成了切比雪夫距离之后就变成了一个正着的正方形了。
不难发现,无论怎么操作,每个点对之间的距离(无论是曼哈顿还是切比雪夫)都是不变的。
因此,在转换成了切比雪夫距离之后,只要知道了最终可以到达的集合 \(p\) 中有哪些点,答案就是所有以这些点为几何中心,边长为 \(2dis\) 的正方形的边上的点的个数之和。
形式化地说,有 \(
\begin{aligned}
ans&=\sum^{}_{i\in p} \sum^{n}_{j=1} ([x_{j}=x_{i}+dis,|y_{i}-y_{j}|\leq dis]+[x_{j}=x_{i}+dis,|y_{i}-y_{j}|\leq dis]+[x_{j}=x_{i}+dis,|y_{i}-y_{j}|\leq dis]+[x_{j}=x_{i}+dis,|y_{i}-y_{j}|\leq dis])
\end{aligned}
\)
这个东西可以用动态开点线段树维护,只需要支持单点插入和区间询问,比较好写,不过要记得特判一下正方形的四个角,否则会被算两次,特判方法可以看代码。
这里的时间复杂度是 \(O(n \log n)\)
接下来是解决如何得到集合 \(p\) 了。其实这个也不难,可以离散化,对每一个 \(x\) 开一个 set,然后做一次 bfs ,直接暴力地去正方形四条边上找,把遍历到的点全部删掉。
因为每一个点只会被删除一次,因此这个地方的时间复杂度也是 \(O(n \log n)\) 。
最后记得答案要除以二,因为点对是无序的,上面计算的过程中每一个点对都被统计了两次。
Code
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ri register int
#define ll long long
#define ui unsigned int
il ll read(){
bool f=true;ll x=0;
register char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=false;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
if(f) return x;
return ~(--x);
}
il void write(const ll &x){if(x>9) write(x/10);putchar(x%10+'0');}
il void print(const ll &x) {x<0?putchar('-'),write(~(x-1)):write(x);putchar('\n');}
il ll max(const ll &a,const ll &b){return a>b?a:b;}
il ll min(const ll &a,const ll &b){return a<b?a:b;}
const int MAXN=1e5+7;
struct node
{
ll x,y;
}p[MAXN];
#define pll pair<ll,ll>
int n,a,b;
int mark[MAXN];
ll dis,ans;
#define IT set<pll>::iterator
struct seg
{
struct T
{
int c[2],sum;
}t[MAXN<<8];
#define mid (L+R>>1)
#define lc t[u].c[0]
#define rc t[u].c[1]
int cnt;
void update(int u){
t[u].sum=0;
if(lc) t[u].sum+=t[lc].sum;
if(rc) t[u].sum+=t[rc].sum;
}
void insert(int &u,int pos,ll L=-2e9,ll R=2e9){
if(!u) u=++cnt;
if(L==pos&&R==pos){
t[u].sum=1;
return;
}
if(pos<=mid) insert(lc,pos,L,mid);
else insert(rc,pos,mid+1,R);
update(u);
}
ll query(int u,int l,int r,ll L=-2e9,ll R=2e9){
if(!u||l>r) return 0;
if(L==l&&R==r) return t[u].sum;
if(r<=mid) return query(lc,l,r,L,mid);
else if(l>mid) return query(rc,l,r,mid+1,R);
else return (query(lc,l,mid,L,mid)+query(rc,mid+1,r,mid+1,R));
}
#undef lc
#undef rc
#undef mid
}T[2];
int root[2][MAXN<<2];
int cnt;
#define pll pair<ll,ll>
#define IT set<pll>::iterator
set<pll> f[2][MAXN<<2];
map<int,int> id[2];
int main(){
n=read(),a=read(),b=read();
for(ri i=1;i<=n;++i){
ll x=read(),y=read();
p[i].x=x+y,p[i].y=x-y;
if(!id[0].count(p[i].x)) id[0][p[i].x]=++cnt;
T[0].insert(root[0][id[0][p[i].x]],p[i].y);
f[0][id[0][p[i].x]].insert((pll){p[i].y,i});
if(!id[1].count(p[i].y)) id[1][p[i].y]=++cnt;
T[1].insert(root[1][id[1][p[i].y]],p[i].x);
f[1][id[1][p[i].y]].insert((pll){p[i].x,i});
}
dis=max(abs(p[a].x-p[b].x),abs(p[a].y-p[b].y));
queue<int> q;
q.push(a),q.push(b);
while(!q.empty()){
int u=q.front();q.pop();
if(mark[u]) continue;
mark[u]=1;
if(id[0].count(p[u].x+dis)){
int now=id[0][p[u].x+dis];
ans+=T[0].query(root[0][now],max(-2e9,p[u].y-dis),min(2e9,p[u].y+dis));
set<pll> &s=f[0][now];
for(IT it=s.lower_bound((pll){p[u].y-dis,0});it!=s.end()&&abs(it->first-p[u].y)<=dis;it=s.erase(it)) q.push(it->second);
}
if(id[0].count(p[u].x-dis)){
int now=id[0][p[u].x-dis];
ans+=T[0].query(root[0][now],max(-2e9,p[u].y-dis),min(2e9,p[u].y+dis));
set<pll> &s=f[0][now];
for(IT it=s.lower_bound((pll){p[u].y-dis,0});it!=s.end()&&abs(it->first-p[u].y)<=dis;it=s.erase(it)) q.push(it->second);
}
if(id[1].count(p[u].y+dis)){
int now=id[1][p[u].y+dis];
ans+=T[1].query(root[1][now],max(-2e9,p[u].x-dis+1),min(2e9,p[u].x+dis-1));
set<pll> &s=f[1][now];
for(IT it=s.lower_bound((pll){p[u].x-dis,0});it!=s.end()&&abs(it->first-p[u].x)<=dis;it=s.erase(it)) q.push(it->second);
}
if(id[1].count(p[u].y-dis)){
int now=id[1][p[u].y-dis];
ans+=T[1].query(root[1][now],max(-2e9,p[u].x-dis+1),min(2e9,p[u].x+dis-1));
set<pll> &s=f[1][now];
for(IT it=s.lower_bound((pll){p[u].x-dis,0});it!=s.end()&&abs(it->first-p[u].x)<=dis;it=s.erase(it)) q.push(it->second);
}
}
print(ans>>1);
return 0;
}

高质量好题+1
浙公网安备 33010602011771号