这道题当时比赛的时候没时间看了(虽然有时间也不一定做得出来_(:з」∠)_),但是其实思路没有那么复杂
主要就是对于每一个询问,因为所覆盖点的数量具有单调性,因此二分枚举所覆盖点的半径,然后可以找出左边点的个数和右边点的个数
若个数==K 则直接返回左右点的标号,若个数==k + 1则需要判断一下左右边点的标记号哪一个较小,然后舍弃较大的那个,直接返回左右标号
具体看代码吧~
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int SIZEN = 100005;
struct elem{
int x,id;
double val;
bool operator < (const elem &a)const{
return x < a.x;
}
};
elem ss[SIZEN];
int hash[SIZEN];
double sum[SIZEN];
int n;
int read(){
char ch = ' ';
while(ch < '0' || ch > '9') ch = getchar();
int ans = 0;
while(ch <= '9' && ch >= '0'){
ans *= 10;
ans += ch - '0';
ch = getchar();
}
return ans;
}
int lowbit(int x){
return x & (-x);
}
void add(int x,double c){
for(int i = x ; i < SIZEN ; i += lowbit(i))
sum[i] += c;
}
double query(int x){
double ans = 0;
for(int i = x ; i ; i -= lowbit(i))
ans += sum[i];
return ans;
}
/*int Find_left(int R,int id){
int l = 1 , r = id;
int ans = 0;
while(l < r){
int mid = (l + r) >> 1;
if(ss[id].x - ss[mid].x > R) l = mid + 1;
else ans = mid,r = mid;
}
return ans;
}
int Find_right(int R,int id){
int l = id ,r = n;
int ans = n;
while(l < r){
int mid = (l + r) >> 1;
if(ss[mid].x - ss[id].x > R) r = mid - 1;
else ans = mid,l = mid;
}
return ans;
}*/
void Find(int &L,int &R,int id,int k){
int l,r;
l = 1 , r = ss[n].x;
while(l <= r){
int mid = (l + r) >> 1;
int t_l = ss[id].x - mid;
int t_r = ss[id].x + mid;
elem ts;
ts.x = t_l;
t_l = lower_bound(ss + 1 ,ss + n + 1 , ts) - ss;
ts.x = t_r;
t_r = upper_bound(ss + 1 ,ss + n + 1 , ts) - ss - 1;
int t_cnt = t_r - t_l;
if(t_cnt == k + 1){
if(ss[id].x - ss[t_l].x == ss[t_r].x - ss[id].x){
L = t_l;
R = t_r;
if(ss[t_l].id < ss[t_r].id) R --;
else L ++;
return;
}
}
if(t_cnt == k){
L = t_l;
R = t_r;
return;
}
else if(t_cnt > k) r = mid - 1;
else l = mid + 1;
}
return;
}
void init(){
memset(sum,0,sizeof(sum));
}
void solve(){
int q,k,m;
double ans = 0;
n = read(); m = read();
init();
for(int i = 1 ; i <= n ; i ++){
ss[i].x = read();ss[i].val = read();
ss[i].id = i;
}
sort(ss + 1,ss + n + 1);
for(int i = 1 ; i <= n ; i ++)
hash[ss[i].id] = i;
for(int i = 1 ; i <= n ; i ++)
add(i,ss[i].val);
while(m--){
int l,r;
q = read();k = read();
int id = hash[q];
Find(l,r,id,k);
double t_val = ss[id].val;
double t_ans = (query(r) - query(l - 1) - t_val) / k;
add(id,- t_val + t_ans);
ans += t_ans;
ss[id].val = t_ans;
}
printf("%.3f\n",ans);
}
int main()
{
int _;
scanf("%d",&_);
while(_--) solve();
}