题目转送门:http://qscoj.cn/#/problem/show/1921
因为A很大,所以需要先离散化,然后建树,对于每个A - len 的位置二分查找位置,用线段树询问区间和最大最小值即可
代码如下
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
struct node { int A,B; }p[maxn];
int sum[maxn<<2],maxx[maxn<<2],minn[maxn<<2];
int sum1,max1 = -INT_MAX,min1 = INT_MAX;
int n,c,len;
void up(int id){
sum[id] = sum[id<<1] + sum[id<<1|1];
maxx[id] = max(maxx[id<<1] , maxx[id<<1|1]);
minn[id] = min(minn[id<<1] , minn[id<<1|1]);
}
void build(int l,int r,int id){
if (l == r){
sum[id] = p[l].B;
maxx[id] = p[l].B;
minn[id] = p[l].B;
return ;
}
int mid = (l + r) >> 1;
build(l, mid, id<<1);
build(mid+1, r, id<<1|1);
up(id);
}
void query(int l,int r,int L,int R,int id){
if (L <= l && r <= R){
sum1 += sum[id];
max1 = max(max1, maxx[id]);
min1 = min(min1, minn[id]);
return;
}
int mid = (l + r )>> 1;
if (L <= mid) query(l, mid, L, R, id<<1);
if (R > mid) query(mid+1, r, L, R, id<<1|1);
}
int low(int v){
int l = 1, r = n;
while (l != r) {
int mid = (l + r) >> 1;
if (p[mid].A > v) r = mid;
else l = mid + 1;
}
return l;
}
int solve(string k,string fun){
int cnt = 0;
for (int i=2; i<=n; i++) {
int x = low(p[i].A - len);
while (p[x].A > p[i].A - len && x != 1) x--;
while (p[x].A < p[i].A - len) x++;
query(1, n, x, i-1, 1);
if (k == "gt"){
if (fun == "min"){
if (p[i].B > min1) cnt++;
}else if (fun == "max"){
if (p[i].B > max1) cnt++;
}else if (fun == "avg"){
if (p[i].B*(i-x) > sum1) cnt++;
}
}else if (k == "lt"){
if (fun == "min"){
if (p[i].B < min1) cnt++;
}else if (fun == "max"){
if (p[i].B < max1) cnt++;
}else if (fun == "avg"){
if (p[i].B*(i-x) < sum1) cnt++;
}
}
sum1 = 0; max1 = -INT_MAX; min1 = INT_MAX;
}
return cnt;
}
int main(){
cin >> n >> c;
for (int i=1; i<=n; i++)
cin >> p[i].A >> p[i].B;
build(1, n, 1);
string k,fun;
for (int i=0; i<c; i++) {
cin >> k >> fun >> len;
cout << solve(k, fun) << endl;
}
return 0;
}