bzoj3053
2017-02-05 14:59
169 查看
k维最近点对。
要求输出前m近点对,用priority_queue存前几名就好,注意估价函数剪枝
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<queue> #define fi first #define se second #define pii pair<int,int> #define MK(a,b) make_pair((a),(b)) #define sqr(x) (x)*(x) using namespace std; const int N=50005; inline int read() { int ans,f=1;char ch; while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0'; while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0'; return ans*f; } int rt,n,k,D,m; struct aa { int l,r; int d[6],mi[6],mx[6]; }a ; void up(int u,int l) { for (int i=0;i<k;i++) a[u].mi[i]=min(a[u].mi[i],a[l].mi[i]), a[u].mx[i]=max(a[u].mx[i],a[l].mx[i]); } bool cmp(aa a,aa b) {return a.d[D]<b.d[D];} int build(int l,int r,int dd) { D=dd;int mid=(l+r)>>1; nth_element(a+l,a+mid,a+r+1,cmp); for (int i=0;i<k;i++) a[mid].mi[i]=a[mid].mx[i]=a[mid].d[i]; if (l!=mid) a[mid].l=build(l,mid-1,(dd+1)%k),up(mid,a[mid].l);else a[mid].l=0; if (r!=mid) a[mid].r=build(mid+1,r,(dd+1)%k),up(mid,a[mid].r);else a[mid].r=0; return mid; } int x[6]; priority_queue<pii> ans; int fdis(int u) { int ans=0; for (int i=0;i<k;i++) ans+=sqr(x[i]-a[u].d[i]); return ans; } int f(int u) { if (u==0) return 1e9; int ans=0; for (int i=0;i<k;i++) { if (a[u].mi[i]>x[i]) ans+=sqr(a[u].mi[i]-x[i]); if (a[u].mx[i]<x[i]) ans+=sqr(x[i]-a[u].mx[i]); } return ans; } void query(int u) { int dis=fdis(u); int dl=f(a[u].l),dr=f(a[u].r); if (ans.size()<m) ans.push(MK(dis,u)); else if (ans.top().fi>dis) {ans.pop();ans.push(MK(dis,u));} if (dl<dr) {if (ans.size()<m||ans.top().fi>dl) query(a[u].l);if (ans.size()<m||ans.top().fi>dr) query(a[u].r);} else {if (ans.size()<m||ans.top().fi>dr) query(a[u].r);if (ans.size()<m||ans.top().fi>dl) query(a[u].l);} } int tmp[15],cnt; void work() { for (int i=1;i<=n;i++) for (int j=0;j<k;j++) a[i].d[j]=read(); rt=build(1,n,0); int t=read(); while (t--) { while (!ans.empty()) ans.pop(); for (int i=0;i<k;i++) x[i]=read();m=read(); query(rt); printf("the closest %d points are:\n",m); cnt=0; while (!ans.empty()) tmp[++cnt]=ans.top().se,ans.pop(); for (int i=cnt;i>=1;i--) { for (int j=0;j<k-1;j++) printf("%d ",a[tmp[i]].d[j]); printf("%d\n",a[tmp[i]].d[k-1]); } } } int main() { while (scanf("%d%d",&n,&k)!=EOF) work(); return 0; }
相关文章推荐
- codevs 数字反转 1130
- GreenOpenPaint的实现(一)基本框架_0
- 五分钟读懂UML类图
- Linux Malloc分析-从用户空间到内核空间
- C#正则表达式匹配被双引号包起来的中文并返回匹配的结果
- linux下搭建svn服务器
- JS方法实现div容器y轴滚动
- (八)git更改提交操作
- 第k小整数
- 多线程时指定某一个线程处理所有信号
- DBGridEh用法总结一
- 关于STL map的for each
- 电商系统订单分表方案怎么设计更好
- Servlet响应乱码问题
- linux内核线程 [实现]
- BZOJ 1102: [POI2007]山峰和山谷Grz FloodFill 算法
- Android lambda 笔记(二)
- springmvc freemarker 之间的传参问题练习 出问题出现在配置文件上
- 唯品会的订单分库分表实践总结以及关键步骤
- Unreal Engine 4 —— 常见Tips