「题解」洛谷 P2709 小B的询问

题目

P2709 小B的询问

思路

莫队板子,统计数字出现次数。

Code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 50001

typedef long long ll;
ll ans[M];
int n, m, k, sqrn;
int a[M], num[M], cnt[M];
struct query {
    int x, y, id;
    friend bool operator < (query q1, query q2) {
        if (num[q1.x] == num[q2.x]) return q1.y < q2.y;
        return num[q1.x] < num[q2.x];
    }
}q[M];

void add(int x, ll &now) {
    int temp = cnt[x];
    ++cnt[x];
    now = now - 1ll * temp * temp + 1ll * cnt[x] * cnt[x];
}

void del(int x, ll &now) {
    int temp = cnt[x];
    --cnt[x];
    now = now - 1ll * temp * temp + 1ll * cnt[x] * cnt[x];
}

int main() {
    scanf("%d %d %d", &n, &m, &k), sqrn = n / sqrt(m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        num[i] = (i - 1) / sqrn + 1;
    }
    for (int i = 1; i <= m; ++i) {
        scanf("%d %d", &q[i].x, &q[i].y);
        q[i].id = i;
    }
    std::sort(q + 1, q + m + 1);
    ll now = 1;
    int l = 1, r = 1; cnt[a[1]] = 1;
    for (int i = 1; i <= m; ++i) {
        while (l > q[i].x) add(a[--l], now);
        while (r < q[i].y) add(a[++r], now);
        while (l < q[i].x) del(a[l++], now);
        while (r > q[i].y) del(a[r--], now);
        ans[q[i].id] = now;
    }
    for (int i = 1; i <= m; ++i) printf("%lld\n", ans[i]);
    return 0;
}
posted @ 2020-10-30 14:49  yu__xuan  阅读(45)  评论(0编辑  收藏  举报