树状数组

给n, m,

给n个数字, 表示位置i的数字的排名,

再给m个询问, 一个询问由a, b组成, 代表着要询问前i个数字中, 排名前b的数目.

 

当时想了好久好久, 但是一点意识也没有qwq.

后来...看了别人的想法后, 突然就懂了点...

 

这种问题吧, 我感觉是要先确定一些顺序, 再根据已有的顺序进行操作.

比如这里, 先确定询问的顺序, 把询问依据a排序, 这样的话, 对每一个询问, 可以通过树状数组快速得到答案.

并且这样只增加, 不减少, 时间复杂度为O(nlogn)(n, m是同阶的)

说得不清楚, 还是看代码吧.

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN = 1e5 + 600;
int bit[MAXN], n, m;
int a[MAXN];
void modify(int i, int v){
    while(i <= n){
        bit[i] += v;
        i += i & -i;
    }
}
int query(int i){
    int rst = 0;
    while(i){
        rst += bit[i];
        i -= i & -i;
    }
    return rst;
}
struct Query{
    int a, b, c;
    bool operator<(const Query & rhs) const{
        return a < rhs.a;
    }
} queries[MAXN];
int results[MAXN];
int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i){// 学号从1开始
        scanf("%d", a + i);
    }
    for(int i = 0; i < m; ++i){// 读取询问
        scanf("%d%d", &queries[i].a, &queries[i].b);// 注意取地址符...
        queries[i].c = i;
    }
    sort(queries, queries + m);// 离线查询, 排序询问
    int cur = 0;// 当前要接受询问的位置, 范围是[0, m)
    for(int i = 1; i <= n; ++i){
        modify(a[i], 1);
        while(cur < m && i == queries[cur].a){// 这个地方慢慢推敲下...要注意cur的范围
            results[queries[cur].c] = query(queries[cur].b);
            ++cur;
        }
    }
    for(int i = 0; i < m; ++i){
        printf("%d\n", results[i]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值