计蒜客习题:校长的问题

问题描述

学校中有 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;
}

猜你喜欢

转载自blog.csdn.net/liukairui/article/details/80920243