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. Python入门必学:字符串和编码正确的使用方法

    字符编码,我们已经讲过了,字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特 ...

  2. 【Isamaru, Hound of Honda】SVN常用命令补遗

    一些常用的 就是svn commit的时候 都必须是最新版本的东西 不能不是,但是其实只是.svn在控制,所以可以update到最新版本再svn merge -r 20:10 将版本10和20的融合, ...

  3. 笔记-python-__new__()

    笔记-python-__new__() 1.       __new__() __new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前. 验证代码: class Person(obj ...

  4. SSH无密码登录及远程拷贝命令SCP的使用

    SSH无密码登录 1.生成密钥对(公钥和私钥) $ cd /home/cen/.ssh $ ssh-keygen -t rsa #生成密钥,使用rsa方式进行加密,四个回车 $ ssh-copy-id ...

  5. 有三个线程T1 T2 T3,如何保证他们按顺序执行

    T3先执行,在T3的run中,调用t2.join,让t2执行完成后再执行t3 在T2的run中,调用t1.join,让t1执行完成后再让T2执行 public class JoinTest {     ...

  6. session为什么需要持久化

    为什么需要持久化: 客户端访问了某个能开启会话功能的资源, web服务器就会创建一个与该客户端对应的HttpSession对象,每个HttpSession对象都要站用一定的内存空间.如果在某一时间段内 ...

  7. wim

    wim 编辑 WIM是英文Microsoft Windows Imaging Format(WIM)的简称,它是Windows基于文件的映像格式.WIM 映像格式并非现在相当常见的基于扇区的映像格式, ...

  8. 45、gridview在改变位置之后无法完整显示的问题记录

    gridview的父布局为layoutFather,gridview id为 layoutGridview layoutFather   高度设置为130dp layoutGridview高度设置为1 ...

  9. Hive jdbc连接出现java.sql.SQLException: enabling autocommit is not supported

    1.代码如下 String url = "jdbc:hive2://master135:10000/default"; String user = "root" ...

  10. thinkphp3.2接入支付宝支付接口(PC端)

    下载支付宝接口包    点击这里        提取密码:aryp 整个接口核心类文件 alipay.config.php是相关参数的配置文件 alipayapi.php 是支付宝接口入口文件 not ...