Fast Queries

 

传送门

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

#define int long long
using namespace std;
const int maxn = 1e5 + 10;
int T, n, q, block, a[maxn], ans, cnt[maxn], res[maxn];

struct node {
    int l, r, id;
} t[maxn];
bool cmp(node a, node b) {//按照奇偶性排序
    if ((a.l / block) == (b.l / block)) {//当左端点位于同一个块时
        if ((a.l / block) % 2)//左端点的块序号为奇数时
            return a.r < b.r;//按照从小到大排
        else//左端点的块序号为偶数时
            return a.r > b.r;//按照从大到小排
    } else//当左端点不位于同一个块时
        return a.l < b.l;//按照块的位置进行排序
    //return (a.l/block)^(b.l/block) ? a.l<b.l : ( ((a.l/block)&1)?a.r<b.r:a.r>b.r );
}

void add(int x) {
    cnt[x]++;
    if (cnt[x] == 1)
        ans++;
}

void del(int x) {
    cnt[x]--;
    if (!cnt[x])
        ans--;
}

void work() {
    int L = t[1].l, R = t[1].l - 1;
    ans = 0;
    for (int i = 1; i <= q; i++) {
        while (L > t[i].l) add(a[--L]);
        while (R < t[i].r) add(a[++R]);
        while (L < t[i].l) del(a[L++]);
        while (R > t[i].r) del(a[R--]);
        res[t[i].id] = ans;
    }
}

signed main() {
    //freopen("in", "r", stdin);
    cin >> T;
    for (int k = 1; k <= T; k++) {
        memset(cnt, 0, sizeof(cnt));
        scanf("%lld%lld", &n, &q);
        block = sqrt(1.0 * n);
        for (int i = 1; i <= n; i++)
            scanf("%lld", &a[i]);
        for (int i = 1; i <= q; i++) {
            scanf("%lld%lld", &t[i].l, &t[i].r);
            t[i].id = i;
        }
        printf("Case %lld:\n", k);
        sort(t + 1, t + q + 1, cmp);
        work();
        for (int i = 1; i <= q; i++)
            printf("%lld\n", res[i]);
    }
    return 0;
}

 

posted @ 2019-11-09 20:56  Hazelxcf  阅读(85)  评论(0)    收藏  举报