【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;
}
时间: 2024-08-07 08:37:14

【BZOJ2626】JZPFAR KDtree的相关文章

【BZOJ2626】JZPFAR kd-tree+堆

[BZOJ2626]JZPFAR Description 平面上有n个点.现在有m次询问,每次给定一个点(px, py)和一个整数k,输出n个点中离(px, py)的距离第k大的点的标号.如果有两个(或多个)点距离(px, py)相同,那么认为标号较小的点距离较大. Input 第一行,一个整数n,表示点的个数. 下面n行,每行两个整数x_i, y_i,表示n个点的坐标.点的标号按照输入顺序,分别为1..n. 下面一行,一个整数m,表示询问个数. 下面m行,每行三个整数px_i, py_i, k

【BZOJ4358】permu kd-tree

[BZOJ4358]permu Description 给出一个长度为n的排列P(P1,P2,...Pn),以及m个询问.每次询问某个区间[l,r]中,最长的值域连续段长度. Input 第一行两个整数n,m. 接下来一行n个整数,描述P. 接下来m行,每行两个整数l,r,描述一组询问. Output 对于每组询问,输出一行一个整数,描述答案. Sample Input 8 3 3 1 7 2 5 8 6 4 1 4 5 8 1 7 Sample Output 3 3 4 HINT 对于询问[1

【BZOJ】【2626】JZPFAR

KD-Tree 0.0找第k大…… 裸KD-Tree……跟之前那道找最近的k个点大同小异 一开始理解错:第K大是第K远……不是第K近……(Tunix你个sb 感觉容易出错的是0号点= =边界情况需要仔细处理……根据题意而定的,比如这题就必须将0号点的距离设置成最近……比如-2……(因为我一开始向堆里加的占位点的距离是-1 1 /************************************************************** 2 Problem: 2626 3 User

【bzoj2989】数列 KD-tree

题目描述 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]|. 2种操作(k都是正整数): 1.Modify x k:将第x个数的值修改为k. 2.Query x k:询问有几个i满足graze(x,i)<=k.因为可持久化数据结构的流行,询问不仅要考虑当前数列,还要 考虑任意历史版本,即统计任意位置上出现过的任意数值与当前的a[x]的graze值<=k的对数.(某位置多次修改为 同样的数值,按

【BZOJ4605】崂山白花蛇草水 权值线段树+kd-tree

[BZOJ4605]崂山白花蛇草水 Description 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实力,他轻松地进了山东省省队,现在便是他履行诺言的时候了.蒟蒻Bob特地为他准备了999,999,999,999,999,999瓶崂山白花蛇草水,想要灌神犇Aleph.神犇Aleph求(跪着的)蒟蒻Bob不要灌他,由于神犇Aleph是神犇,蒟蒻Bob最终答应了他的请求,但蒟蒻Bob决定将计就计,也让神犇Aleph回答

【BZOJ3489】A simple rmq problem kd-tree

[BZOJ3489]A simple rmq problem Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直接输出0.我会采取一些措施强制在线. Input 第一行为两个整数N,M.M是询问数,N是序列的长度(N<=100000,M<=200000) 第二行为N个整数,描述这个序列{ai},其中所有1<=ai<=N 再下面M行,每

【BZOJ4066】简单题 KDtree

[BZOJ4066]简单题 Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 将格子x,y里的数字加上A 2 x1 y1 x2 y2 1<=x1<= x2<=N 1<=y1<= y2<=N 输出x1 y1 x2 y2这个矩形内的数字和 3 无 终止程序 Input 输入文件第一行一个正整数N. 接下来每行一个操作.每条命令除第

【BZOJ4520】[Cqoi2016]K远点对 kd-tree+堆

[BZOJ4520][Cqoi2016]K远点对 Description 已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对. Input 输入文件第一行为用空格隔开的两个整数 N, K.接下来 N 行,每行两个整数 X,Y,表示一个点的坐标.1 < =  N < =  100000, 1 < =  K < =  100, K < =  N*(N−1)/2 , 0 < =  X, Y < 2^31. Output 输出文件第一行为一个整数,表示第 K 远点对

【BZOJ2850】巧克力王国 KDtree

[BZOJ2850]巧克力王国 Description 巧克力王国里的巧克力都是由牛奶和可可做成的.但是并不是每一块巧克力都受王国人民的欢迎,因为大家都不喜 欢过于甜的巧克力.对于每一块巧克力,我们设x和y为其牛奶和可可的含量.由于每个人对于甜的程度都有自己的 评判标准,所以每个人都有两个参数a和b,分别为他自己为牛奶和可可定义的权重,因此牛奶和可可含量分别为x 和y的巧克力对于他的甜味程度即为ax + by.而每个人又有一个甜味限度c,所有甜味程度大于等于c的巧克力他都 无法接受.每块巧克力都