问题描述
学校中有 n 名学生,学号分别为 1…n。再一次考试过后,学校按照学生的分数排了一个名次(分数一样,按照名字的字典序排序)。你是一名老师,你明天要和校长汇报这次考试的考试情况,校长询问的方式很奇怪,比如说:“学号前 a 的人中,排名前 b 的有多少人?”。
校长问了一堆这样的问题,你需要今天全部计算出来,明天好向他汇报。
输入格式
第一行俩个整数,n 和 m,分别表示学校学生的数量和校长问题的数量。(1≤n,m≤105)
第二行有 n 个整数,表示按学号顺序这 n 个学生在这次考试中对应的排名。
接下来 m 行,每行俩个整数 a, b 表示校长的问题中的具体数字。(1≤a,b≤n)
输出格式
输出 m 行,每行一个整数代表校长问题的答案。
样例输入
6 3
3 2 5 4 6 1
4 4
2 5
6 4
样例输出
3
2
4
AC代码
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 100010;
vector<int> v[MAXN];
vector<int> id[MAXN];
int tree[MAXN];
int a[MAXN];
int ans[MAXN];
int n, m;
int ta;
int tb;
int lowbit(int x) {
return x & -x;
}
void update(int x, int v) {
for (int i = x; i < MAXN; i += lowbit(i)) {
tree[i] += v;
}
}
int get(int x) {
int ret = 0;
for (int i = x; i > 0; i -= lowbit(i)) {
ret += tree[i];
}
return ret;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
int tot = 0;
for (int i = 0; i < m; ++i) {
scanf("%d %d", &ta, &tb);
v[ta].push_back(tb);
id[ta].push_back(tot);
tot++;
}
for (int i = 1; i <= n; ++i) {
update(a[i-1], 1);
for (size_t j = 0; j < v[i].size(); ++j) {
ans[id[i][j]] = get(v[i][j]);
}
}
for (int i = 0; i < m; ++i) {
printf("%d\n", ans[i]);
}
return 0;
}