【BZOJ2626】JZPFAR KDtree

题解:KDT,暴力维护前K大,,或许可以用个pq。


呃,我的代码WA了,但是pai了好久都没pai出来,,,,,而且我的代码是当前交的AC代码的效率的正好3倍!!!



纠结啊~~~

WA代码:

#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 101000
#define inf 0x3f3f3f3f
#define d(x,y) (((x)>(y))?((x)-(y)):((y)-(x)))
using namespace std;

int n,q;

int judge;
struct Point
{
	int x,y;
	int id;
	Point(int _x=0,int _y=0):x(_x),y(_y){}
	bool operator < (const Point &a)const
	{return judge?y<a.y:x<a.x;}
}P[N];
inline int dis(Point &a,Point &b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
struct ANS
{
	int id;
	int x;
	ANS(int _id=0,int _x=0):id(_id),x(_x){}
	bool operator < (const ANS &a)const{return x==a.x?id<a.id:x>a.x;}
};
priority_queue<ANS>pq;
struct KDT
{
	int son[N][2],cnt;
	int x[N][2],y[N][2];
	void init(int a,Point &p)
	{
		x[a][0]=x[a][1]=p.x;
		y[a][0]=y[a][1]=p.y;
	}
	void update(int f)
	{
		int s;
		if(son[f][0])
		{
			s=son[f][0];
			x[f][0]=min(x[f][0],x[s][0]);
			y[f][0]=min(y[f][0],y[s][0]);
			x[f][1]=max(x[f][1],x[s][1]);
			y[f][1]=max(y[f][1],y[s][1]);
		}
		if(son[f][1])
		{
			s=son[f][1];
			x[f][0]=min(x[f][0],x[s][0]);
			y[f][0]=min(y[f][0],y[s][0]);
			x[f][1]=max(x[f][1],x[s][1]);
			y[f][1]=max(y[f][1],y[s][1]);
		}
	}
	int maxdis(int a,Point &p)
	{
		int e=max(d(x[a][0],p.x),d(x[a][1],p.x)),
		b=max(d(y[a][0],p.y),d(y[a][1],p.y));
		return e*e+b*b;
	}
	int newnode(Point &p)
	{
		init(++cnt,p);
		return cnt;
	}
	int build(int l,int r,int jd=0)
	{
		int mid=l+r>>1,t=0;
		judge=jd;
		nth_element(P+l,P+mid,P+r+1);
		if(l<mid)t=build(l,mid-1,!jd);
		int q=newnode(P[mid]);son[q][0]=t;
		if(mid<r)son[q][1]=build(mid+1,r,!jd);
		update(q);
		return q;
	}
	void query(int f,Point &p)
	{
		int Dis[3];
		ANS tt=pq.top();
		Dis[2]=dis(P[f],p);
		if(tt.x<Dis[2]||(tt.x==Dis[2]&&tt.id>P[f].id))
		{
			pq.pop();
			pq.push(ANS(P[f].id,Dis[2]));
			tt=pq.top();
		}
		Dis[0]=Dis[1]=0;
		if(son[f][0])Dis[0]=maxdis(son[f][0],p);
		if(son[f][1])Dis[1]=maxdis(son[f][1],p);
		for(int i=2,t=Dis[0]<Dis[1];i--;t^=1)
			if(son[f][t]&&Dis[t]>=tt.x)query(son[f][t],p);
	}
}kdt;
int main()
{
//	freopen("test.in","r",stdin);
	int i,k,root=0;
	int x,y;
	Point pp;
	for(scanf("%d",&n),i=1;i<=n;i++)scanf("%d%d",&P[i].x,&P[i].y),P[i].id=i;
	if(n)root=kdt.build(1,n);
	for(scanf("%d",&q);q--;)
	{
		scanf("%d%d%d",&x,&y,&k);
		while(!pq.empty())pq.pop();
		while(k--)pq.push(ANS(inf,0));

		pp=Point(x,y);
		kdt.query(root,pp);

		ANS doubi=pq.top();
		printf("%d\n",doubi.id);
	}
	return 0;
}


AC代码:

#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
#define INF 0x3f3f3f3f 
using namespace std;

int dim;

struct Point{
  long long x,y;
  int id;
  
  Point(long long _ = 0,long long __ = 0):x(_),y(__) {}
  bool operator <(const Point &a)const {
    if(dim) return x < a.x;
    return y < a.y;
  }
  void Read(int p) {
    scanf("%lld%lld",&x,&y);
    id = p;
  }
}point[MAX];

inline long long Calc(const Point &p1,const Point &p2)
{
  return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);
}

struct KDTree{
  KDTree *son[2];
  Point root;
  long long x0,y0,x1,y1;
  
  KDTree(KDTree *_,KDTree *__,Point ___) {
    son[0] = _,son[1] = __;
    root = ___;
    x0 = x1 = ___.x;
    y0 = y1 = ___.y;
  }
  KDTree() {}
  void Maintain(KDTree *a) {
    x0 = min(x0,a->x0);
    x1 = max(x1,a->x1);
    y0 = min(y0,a->y0);
    y1 = max(y1,a->y1);
  }
  long long Dis(const Point &p) {
    long long re = 0;
    re = max(re,Calc(p,Point(x0,y0)));
    re = max(re,Calc(p,Point(x1,y0)));
    re = max(re,Calc(p,Point(x1,y1)));
    re = max(re,Calc(p,Point(x0,y1)));
    return re;
  }
}*root,none,*nil = &none;

struct Complex{
  long long dis;
  int id;
  
  Complex(long long _,int __):dis(_),id(__) {}
  bool operator <(const Complex &a)const {
    if(dis == a.dis)  return id < a.id;
    return dis > a.dis;
  }
};

int cnt,asks;

KDTree *BuildTree(int l,int r,int d)
{
  if(l > r) return nil;
  dim = d;
  int mid = (l + r) >> 1;
  nth_element(point + l,point + mid,point + r + 1);
  KDTree *re = new KDTree(BuildTree(l,mid - 1,!d),BuildTree(mid + 1,r,!d),point[mid]);
  if(re->son[0] != nil) re->Maintain(re->son[0]);
  if(re->son[1] != nil) re->Maintain(re->son[1]);
  return re;
}

priority_queue<Complex> q;

void Ask(KDTree *a,const Point &p)
{
  long long dis = Calc(p,a->root);
  Complex temp(dis,a->root.id);
  if(temp < q.top()) {
    q.push(temp);
    q.pop();
  }
  long long l = a->son[0] == nil ? -1:a->son[0]->Dis(p);
  long long r = a->son[1] == nil ? -1:a->son[1]->Dis(p);
  if(l > r) {
    if(a->son[0] != nil)
      Ask(a->son[0],p);
    if(a->son[1] != nil && r >= q.top().dis)
      Ask(a->son[1],p);
  }
  else {
    if(a->son[1] != nil)
      Ask(a->son[1],p);
    if(a->son[0] != nil && l >= q.top().dis)
      Ask(a->son[0],p);
  }
}

int main()
{
  cin >> cnt;
  for(int i = 1; i <= cnt; ++i)
    point[i].Read(i);
  root = BuildTree(1,cnt,0);
  cin >> asks;
  for(int k,i = 1; i <= asks; ++i) {
    Point p;
    p.Read(0);
    scanf("%d",&k);
    while(!q.empty()) q.pop();
    for(int i = 1; i <= k; ++i) q.push(Complex(-INF,0));
    Ask(root,p);
    printf("%d\n",q.top().id);
  }
  return 0;
}


数据生成器:

#include <ctime>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100000
#define inf 0x3f3f3f3f
using namespace std;
int n,m;
int main()
{
	srand((unsigned)time(NULL));
	int i,j,k;
	int a,b,c;
	n=rand()%N+1;
	m=rand()%N+1;

	printf("%d\n",n);
	for(i=1;i<=n;i++)printf("%d %d\n",rand()%100-50,rand()%100-50);
	printf("%d\n",m);
	while(m--)printf("%d %d %d\n",rand()%100-50,rand()%100-50,rand()%n+1);
	return 0;
}


拍子:

#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 30000
using namespace std;

int main()
{
	int i,g;
	system("g++ std.cpp -o std -g -O3");
	system("g++ my.cpp -o my -g -O3");
	system("g++ rand.cpp -o rand -g -O3");
	for(g=1;;g++)
	{
		printf("Case %d :   ",g);
		system("rand>test.in");
		clock_t j=clock();
		system("my <test.in >my.out");
		clock_t k=clock();
		printf("my_use : %03dms  ",k-j);
		system("std <test.in >std.out");
		printf("std_use : %03dms  ",clock()-k);
		if(system("fc std.out my.out >NULL")==0){puts("result : AC");}
		else 
		{
			puts("WAWAWAWAWAWAWAWA!!!!!!!!");
			system("start test.in");
			for(i=1;i<=5;i++)printf("\a");
			return 0;
		}
	}
	puts("");
	puts("****,please try again");
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值