询问离线处理模板题
思路:
所有询问按照k从小到大排序,为什么要这样呢?
显然,如果小与等于k1的答案处理出来了,那么怎么处理k2(k2>=k1)的答案呢?
如果在数组中所有小于等于k1的位置被高亮了,那么在数组中所有小于等于k2的高亮位置一定包含k1的
高亮位置,这样从小到大跑过去,最多高亮n个点。那么答案是什么呢?
怎么维护高亮点数呢?
直接用树状数组动态维护。
复杂度O(nlogn)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
struct Query{
int l, r, k;
int id;
}q[maxn];
struct node{
int val; int pos;
}a[maxn];
int n, m;
int ans[maxn], sum[maxn];
int lowbit(int x){
return x & -x;
}
void add(int i, int tmp){
while(i <= n){
sum[i] += tmp;
i += lowbit(i);
}
}
int getsum(int i){
int ans = 0;
while(i){
ans += sum[i];
i -= lowbit(i);
}
return ans;
}
bool cmp(Query a, Query b){
if(a.k == b.k) return a.id < b.id;
return a.k < b.k;
}
bool cmp1(node a, node b){
if(a.val == b.val) return a.pos < b.pos;
return a.val < b.val;
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i].val); a[i].pos = i;
}
sort(a + 1, a + n + 1, cmp1);
int l, r, k;
for(int i = 1; i <= m; i++){
scanf("%d%d%d", &l, &r, &k);
q[i].l = l; q[i].r = r; q[i].k = k; q[i].id = i;
}
sort(q + 1, q + m + 1, cmp);
int j = 1;
for(int i = 1; i <= m; i++){
int k = q[i].k;
for(; j <= n && a[j].val <= k; j++){
add(a[j].pos, 1);
}
ans[q[i].id] = getsum(q[i].r) - getsum(q[i].l - 1);
}
for(int i = 1; i <= m; i++){
printf("%d\n", ans[i]);
}
return 0;
}

