http://acm.hdu.edu.cn/showproblem.php?pid=4995
给定一维坐标下的n个点,以及每个点的权值,有m次查询,每次将查询的x点上的权值修改为离x最近的k个点权值的平均和,有相同取序号小的。最后输出修改值的总和。
先离线处理出每个x点对应的所有最近的k个点,然后模拟即可
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <queue> #include <map> #include <iostream> #include <algorithm> using namespace std; #define RD(x) scanf("%d",&x) #define RD2(x,y) scanf("%d%d",&x,&y) #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define clr0(x) memset(x,0,sizeof(x)) typedef long long LL; const int maxn = 100005; int n,m,k; int g[maxn][11]; double v[maxn]; struct node{ int x,i; }p[maxn]; bool cmp(node a,node b) { return a.x < b.x; } bool lorr(int x,int l,int r) { if(r >= n) return true; if(l < 0) return false; if(p[x].x - p[l].x != p[r].x - p[x].x) return p[x].x - p[l].x < p[r].x - p[x].x; return p[l].i < p[r].i; } void getK(int x) { int l = x - 1,r = x + 1,id = p[x].i; for(int i = 0;i < k;++i) if(lorr(x,l,r)) g[id][i] = p[l--].i; else g[id][i] = p[r++].i; } void init () { scanf("%d%d%d", &n, &m, &k); for (int i = 0; i < n; i++) { scanf("%d%lf", &p[i].x, &v[i]); p[i].i = i; } sort(p , p + n, cmp); for (int i = 0; i < n; i++) getK(i); } int main() { int _,x;RD(_);while(_--){ init(); double ans = 0; while(m--){ RD(x); x--; double sum = 0; for(int i = 0;i < k;++i) sum += v[g[x][i]]; v[x] = sum/k; ans += v[x]; } printf("%.6lf\n",ans); } return 0; }