Revenge of kNN

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 584    Accepted Submission(s): 136

Problem Description
In
pattern recognition, the k-Nearest Neighbors algorithm (or k-NN for
short) is a non-parametric method used for classification and
regression. In both cases, the input consists of the k closest training
examples in the feature space.
In k-NN regression, the output is the
property value for the object. This value is the average of the values
of its k nearest neighbors.
---Wikipedia

Today, kNN takes
revenge on you. You have to handle a kNN case in one-dimensional
coordinate system. There are N points with a position Xi and value Vi.
Then there are M kNN queries for point with index i, recalculate its
value by averaging the values its k-Nearest Neighbors. Note you have to
replace the value of i-th point with the new calculated value. And if
there is a tie while choosing k-Nearest Neighbor, choose the one with
the minimal index first.

 
Input
The first line contains a single integer T, indicating the number of test cases.

Each
test case begins with three integers N, M and K, in which K indicating
the number of k-Nearest Neighbors. Then N lines follows, each line
contains two integers Xi and Vi. Then M lines with the queried index Qi
follows.

[Technical Specification]
1. 1 <= T <= 5
2. 2<=N<= 100 000, 1<=M<=100 000
3. 1 <= K <= min(N – 1, 10)
4. 1 <= Vi <= 1 000
5. 1 <= Xi <= 1 000 000 000, and no two Xi are identical.
6. 1 <= Qi <= N

 
Output
For each test case, output sum of all queries rounded to six fractional digits.
 
Sample Input
1
5 3 2
1 2
2 3
3 6
4 8
5 8
2
3
4
 
Sample Output
17.000000
做这题让我知道了如何解决一个很常见但是也很难想的问题:一个数组如果排序后被打乱了,知道它原来的位置,如何对应出现在的位置?
题意:X轴上有 n 个点,每个点都有个初始位置和权值(这些位置是杂乱无章的),现在给m次询问:每次询问第 i 个给出的点,找出离他最近的 k 个点,然后将 k 个点的权值相加取平均值赋值给当前询问的点,输出的最终答案就是这m 次询问每次询问的平均值之和。还有就是关于 k 个点的选取,当距离相同时,选择给出顺序小的。
题解:由于要找到邻居,排序是无疑的,但是询问却是询问的以前的位置。排完序之后如何找到原来的位置??循环?不行,10^5次询问每次找点也要10^5,肯定会超时?这时我们可以利用一个数组来记录排完序后元素原来的位置。但是,元素的下标是从 1 <= Xi <= 1 000 000 000,数组肯定存不下,怎么办?离散化呗,这样寻找的时间就变成 O(1)了。
可能有人不懂离散化后数组存的意思,这里举个例子:
原来的X轴分布假设为:
3 1 2 100 99
我们记录一下每个Xi 出现的位置 3(1) 1(2) 2(3) 100(4) 99(5)
排个序: 1(2) 2(3) 3(1) 99(5) 100(4)
弄个数组将括号里面的数表示成下标分别赋值给 1-5  a[2]=1 a[3]=2 a[1]=3 a[5]=4 a[4]=5
然后对应查询,假设我们查询初始位置是第 4 位的那个 Xi=100,对应排完序后的数组的位置是 a[4] = 5 而新的数组第5个数字等于100!!是不是很神奇,这就是离散化的好处了.不懂我说的同学可以看下acdreamer大神的博客:http://blog.csdn.net/acdreamers/article/details/8520096
 
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = ;
struct Node{
LL x;
int id1;
double v;
}node[N];
int idx[N];
int cmp(Node a,Node b){
return a.x<b.x;
}
int main()
{
int tcase,n,m,k,x;
scanf("%d",&tcase);
while(tcase--)
{
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<=n;i++){
scanf("%lld%lf",&node[i].x,&node[i].v);
node[i].id1 = i;
}
sort(node+,node++n,cmp);
for(int i=;i<=n;i++){
idx[node[i].id1] = i;
}
double sum = ;
while(m--){
int id;
scanf("%d",&id);
int now = idx[id];
double avg = ;
int l = now-,r = now+;
for(int i=;i<=k;i++){
if(l>=&&r<=n){
LL dis1 = node[now].x - node[l].x;
LL dis2 = node[r].x - node[now].x;
if(dis1<dis2){
avg+=node[l--].v;
}else if(dis1>dis2){
avg+=node[r++].v;
}else { ///相等的话按照邻居原来的下标进行选择
int ori_l = node[l].id1;
int ori_r = node[r].id1;
if(ori_l<ori_r) {
avg+=node[l--].v;
}else{
avg+=node[r++].v;
}
}
}else if(l>=){
avg+=node[l--].v;
}else if(r<=n){
avg+=node[r++].v;
}
}
/* ///不知道WA的原因
int l=1,r=1;
for(int i=1;i<=k;i++){
if(now-l>=1&&now+r<=n){
LL dis1 = node[now].x - node[now-l].x;
LL dis2 = node[now+r].x - node[now].x;
if(dis1<dis2){
avg+=node[now-l].v;
l++;
}else if(dis1>dis2){
avg+=node[now+r].v;
r++;
}else { ///相等的话按照邻居原来的下标进行选择
int ori_l = node[now+l].id1;
int ori_r = node[now+r].id1;
if(ori_l<ori_r) {
avg+=node[now-l].v;
l++;
}else{
avg+=node[now+r].v;
r++;
}
}
}else if(now-l>=1){
avg+=node[now-l].v;
l++;
}else if(now+r<=n){
avg+=node[now+r].v;
r++;
}
}*/
node[now].v = avg/k;
sum+=avg/k;
}
printf("%.6lf\n",sum);
}
return ;
}

hdu 4995(离散化下标+模拟)的更多相关文章

  1. hdu 4995 离线处理+模拟

    http://acm.hdu.edu.cn/showproblem.php?pid=4995 给定一维坐标下的n个点,以及每个点的权值,有m次查询,每次将查询的x点上的权值修改为离x最近的k个点权值的 ...

  2. hdu 5139(离线处理+离散化下标)

    Formula Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  3. R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数

    R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...

  4. BestCoder9 1003 Revenge of kNN(hdu 4995) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4995 题目意思:在一个一维坐标轴上,给出位置 xi 和值 vi,对于 M 次询问,每次询问给出inde ...

  5. POJ2729 Robocode(离散化与模拟-----提醒曾经爱玩游戏的自己没做出这个

    题目链接 :http://poj.org/problem?id=2729 题目很长,有不少也是废话.类似小时候玩的坦克大战.每个坦克速度为10,炮弹速度为20.子弹出界就消失,坦克出不了界限.相向的子 ...

  6. HDU 5510---Bazinga(指针模拟)

    题目链接 http://acm.hdu.edu.cn/search.php?action=listproblem Problem Description Ladies and gentlemen, p ...

  7. HDU 5047 Sawtooth(大数模拟)上海赛区网赛1006

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5047 解题报告:问一个“M”型可以把一个矩形的平面最多分割成多少块. 输入是有n个“M",现 ...

  8. HDU 2836 (离散化DP+区间优化)

    Reference:http://www.cnblogs.com/wuyiqi/archive/2012/03/28/2420916.html 题目链接: http://acm.hdu.edu.cn/ ...

  9. lines---hdu5124(离散化+数组模拟)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5124 就是有n条在x轴的线段,给你线段的左右端点,每条线段都会覆盖点,求出最多被覆盖多少次: #inc ...

随机推荐

  1. kubectl alias auto complete

    平时kubectl命令管理kubernetes,敲久了就觉得比较麻烦,想着使用alias k来代替kubectl,可是当输入k时没有了自动补全的功能 这里在 ~/.bashrc 添加如下配置后,可以自 ...

  2. 各种友(e)善(xin)数论总集(未完待续),从入门到绝望

    目录 快速幂 扩展欧几里得 GCD 扩展欧几里得 同余系列 同余方程 同余方程组 一点想法 高次同余方程 BSGS exBSGS 线性筛素数 埃式筛 欧拉筛 欧拉函数 讲解 两道水题 法雷级数 可见点 ...

  3. HDU 5119 Happy Matt Friends (14北京区域赛 类背包dp)

    Happy Matt Friends Time Limit: 6000/6000 MS (Java/Others)    Memory Limit: 510000/510000 K (Java/Oth ...

  4. HDOJ 2120 Ice_cream's world I

    Ice_cream's world I ice_cream's world is a rich country, it has many fertile lands. Today, the queen ...

  5. android 极光推送 声音与振动 的关闭和开启

    前言:最近刚好在写一些推送方面的东西,又是新手,不断在网上找资料,很少,不过还是找到了一些,反正百度我是再也不想百度了,谷歌一下子就能找到想要的. 废话不多说. 1.主要方法就是如下一个函数 priv ...

  6. Android 获取地理位置信息 封装好了 直接用

    前言:花了一个早上研究了以下android获取经纬度,然后网上的参考资料都是杂七杂八,基本上都是过去几年的,现在我用 android6.0参照别人的结果发生好多错误,我的内心几乎是崩溃的.后来,不断百 ...

  7. Python中bisect的使用方法

    Python中列表(list)的实现其实是一个数组,当要查找某一个元素的时候时间复杂度是O(n),使用list.index()方法,但是随着数据量的上升,list.index()的性能也逐步下降,所以 ...

  8. wap html5播放器和直播开发小结

    此文已由作者吴家联授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 去年年中的时候,借着产品改版的机会,将之前的h5播放器好好整理重构了一番.之前的h5播放器较为简陋,有几个大 ...

  9. C#入门篇6-2:字符串操作 string常用的函数

    //String 字符串的常见操作 public static void Fun1() { string MyStr = " Hello World! "; //length长度属 ...

  10. Jmeter-深入理解cookie,session,token

    1.很久很久以前,Web 基本上就是文档的浏览而已, 既然是浏览,作为服务器, 不需要记录谁在某一段时间里都浏览了什么文档,每次请求都是一个新的HTTP协议, 就是请求加响应,  尤其是我不用记住是谁 ...