题解: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;
}