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