P2202 [USACO13JAN] Square Overlap S

分析

如果想让以 (xi,yi)(x_i,y_i)(xj,yj)(x_j,y_j) 为中心的两个正方形重叠,那么显而易见 xixj<k|x_i-x_j|<kyiyj<k|y_i-y_j|<k

由于 n5×104n \le 5 \times 10^4,所以 O(n2)O(n^2) 的暴力显然过不去,n5×104n \le 5 \times 10^4 放的很宽,根号科技及以下都可以通过,这里提供一个比较暴力的平衡树做法。

将每个点的坐标以横坐标为键值插入 FHQ 后,将原序列按横坐标为关键字从小到大排序。这样就可以直接去 FHQ 里查询后继,如果 xixj<k|x_i-x_j|<k 就去比对 yiy_iyjy_j,之后再判断那三种重叠情况即可。

不知道是不是人傻常数大的缘故,加了从 Darling_zero_two{\color{black}D}{\color{red}arling\_zero\_two} 那里薅来的快读快写跟 inline 等一系列优化才过掉的。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+12;
const int inf=0x3f3f3f3f;
//这个不是Darling_zero_two的快读,是从timedrop那里薅来的
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
template<typename T>inline void read(T& t) {
	int c=getchar(),f=1;
	t=0;
	while(!isdigit(c)) {
		if(c=='-')f=-1;
		c=getchar();
	}
	while(isdigit(c))t=t*10+c-48,c=getchar();
	t*=f;
}
template<typename T,typename ...Args>inline void read(T& t,Args&... args) {
	read(t),read(args...);
}
int cnt=0,root=0,rnkx,rnky;
struct noed {
	int l,r;
	int numx,numy,pri;
	int size;
} t[maxn];
struct pos {
	int x,y;
} a[maxn];

inline bool cmp(pos x,pos y) {
	return x.x<y.x;
}
inline void build(int x,int y) {
	cnt++;
	t[cnt].size=1;
	t[cnt].l=t[cnt].r=0;
	t[cnt].numx=x;
	t[cnt].numy=y;
	t[cnt].pri=rand();
}
inline void split(int p,int x,int &l,int &r) {
	if(p==0) {
		l=r=0;
		return ;
	}
	if(t[p].numx<=x) {
		l=p;
		split(t[p].r,x,t[p].r,r);
	} else {
		r=p;
		split(t[p].l,x,l,t[p].l);
	}
	t[p].size=t[t[p].l].size+t[t[p].r].size+1;
}
inline int merge(int l,int r) {
	if(l==0 or r==0)
		return l+r;
	if(t[l].pri>t[r].pri) {
		t[l].r=merge(t[l].r,r);
		t[l].size=t[t[l].l].size+t[t[l].r].size+1;
		return l;
	} else {
		t[r].l=merge(l,t[r].l);
		t[r].size=t[t[r].l].size+t[t[r].r].size+1;
		return r;
	}
}
inline void insert(int x,int y) {
	int l,r;
	split(root,x,l,r);
	build(x,y);
	int p=merge(l,cnt);
	root=merge(p,r);
}
inline int kp(int p,int x) {
	int num=t[t[p].l].size;
	if(x==num+1)
		return p;
	if(x<=num)
		return kp(t[p].l,x);
	if(x>num)
		return kp(t[p].r,x-t[t[p].l].size-1);
}
inline void nerv(int x) {
	int l,r;
	split(root,x,l,r);
	int o=kp(r,1);
	rnkx=t[o].numx;
	rnky=t[o].numy;
	root=merge(l,r);
	//cout<<" o "<<o<<" x "<<rnkx<<" y "<<rnky<<endl;
}
inline void write(int x) {
	if(x >= 10) write(x / 10);
	putchar(x % 10 + '0');
}
int main() {
	int i,n,k;
	read(n,k);
	insert(inf,inf),insert(-inf,-inf);
	for(i=1; i<=n; i++) {
		read(a[i].x,a[i].y);
		insert(a[i].x,a[i].y);
	}
	sort(a+1,a+n+1,cmp);
	int ans=0;
	for(i=1; i<=n; i++) {
		nerv(a[i].x);
		while(rnkx-a[i].x<k) {
			if(abs(rnky-a[i].y)<k) {
				if(ans) {
					cout<<-1<<endl;
					return 0;
				}
				ans=abs(k-abs(rnkx-a[i].x))*abs(k-abs(rnky-a[i].y));
			}
			nerv(rnkx);
		}
	}
	cout<<ans;

	return 0;
}

备注

posted @ 2023-11-16 22:00  p7gab  阅读(0)  评论(0编辑  收藏  举报  来源