图片说明

思路:
所有询问按照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;
}