[bzoj4520][Cqoi2016]K远点对_KD-Tree_堆

K远点对 bzoj-4520 Cqoi-2016

题目大意:已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对。

注释:$1\le n\le 10^5$,$1\le k\le 100$,$k\le n*(n-1)/2$,$0\le x,y<2^{31}$。


想法

KD-Tree还是很暴力的。

我们只需要考虑直接暴力的维护一个个数为$k$的堆即可。

复杂度什么的都滚蛋吧,反正能过。

Code

#include 
#define inf 10000000000000000ll 
#define N 100010 
using namespace std; typedef long long ll;
char *p1,*p2,buf[100000]; int d,root;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
priority_queue,greater >q;
struct Node {int p[2],ls,rs,mn[2],mx[2];}a[N];
inline bool cmp(const Node &a,const Node &b) {return a.p[d]==b.p[d]?a.p[d^1] void Max(T &x,T y) {x=max(x,y);}
template  void Min(T &x,T y) {x=min(x,y);}
inline void pushup(int x,int k)
{
	Max(a[x].mx[0],a[k].mx[0]); Max(a[x].mx[1],a[k].mx[1]);
	Min(a[x].mn[0],a[k].mn[0]); Min(a[x].mn[1],a[k].mn[1]);
}
int build(int l,int r,int now)
{
	int mid=(l+r)>>1;
	d=now; nth_element(a+l,a+mid,a+r+1,cmp);
	a[mid].mn[0]=a[mid].mx[0]=a[mid].p[0];
	a[mid].mn[1]=a[mid].mx[1]=a[mid].p[1];
	if(lq.top()&&x!=k) q.pop(),q.push(dis);
	if(dl>dr)
	{
		if(dl>q.top()) query(ls,k);
		if(dr>q.top()) query(rs,k);
	}
	else
	{
		if(dr>q.top()) query(rs,k);
		if(dl>q.top()) query(ls,k);
	}
}
int main()
{
	int n=rd(),m=rd(); m*=2;
	for(int i=1;i<=n;i++) a[i].p[0]=rd(),a[i].p[1]=rd();
	root=build(1,n,0);
	for(int i=1;i<=m;i++) q.push(0);
	for(int i=1;i<=n;i++) query(root,i);
	cout << q.top() << endl ;
	return 0;
}

小结:好题。

转载于:https://www.cnblogs.com/ShuraK/p/10239026.html

你可能感兴趣的:([bzoj4520][Cqoi2016]K远点对_KD-Tree_堆)