题意
N个点,M次查询。每次查询求与点Q相邻的最近K个点的平均值,并将点Q的值换为平均值。M次查询后,求平均值之和。
题解
暴力。对N个点按X值进行排序。针对每个点计算出其K临近点。然后,在查询时调用计算出的结果即可。
注意事项
这道题最大的坑是排序以后会导致原输入顺序混乱,而题目中要求,如果与点Q距离相同,则根据输入顺序,选择输入顺序先的点。因此需要在输入点的时候记录输入位置。
代码
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
struct Node{
int x,id;
};
Node nd[120010];
double ndv[120010];
int n,m,k;
int g[120010][11];
int cmmp(Node a,Node b){
if(a.x>b.x){
return 0;
}else{
return 1;
}
}
bool judge(int i,int l,int r){
if(r>n){
return true;
}else if(l<=0){
return false;
}else if(abs(nd[i].x-nd[l].x)!=abs(nd[i].x-nd[r].x)){
return abs(nd[i].x-nd[l].x)<abs(nd[i].x-nd[r].x);
}else{
return nd[l].id<nd[r].id;
}
}
void getN(int i){
int id=nd[i].id;
int l=i-1,r=i+1;
for(int j=0;j<k;j++){
if(judge(i,l,r)){
g[id][j]=nd[l--].id;
}else{
g[id][j]=nd[r++].id;
}
}
}
int main()
{
int kase;
scanf("%d",&kase);
while(kase--){
double allsum=0;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++){
scanf("%d%lf",&nd[i].x,&ndv[i]);
nd[i].id=i;
}
sort(nd+1,nd+n+1,cmmp);
for(int i=1;i<=n;i++){
getN(i);
}
for(int i=0;i<m;i++){
int s;
scanf("%d",&s);
double sum=0;
for(int j=0;j<k;j++){
sum+=ndv[g[s][j]];
}
ndv[s]=sum/k;
allsum+=sum/k;
}
printf("%.6lf\n",allsum);
}
return 0;
}