洛谷 P2709 小B的询问

题意简述

给定一个序列
每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中c(i)表示数字i在[L..R]中的重复次数

题解思路

莫队

代码

#include <cmath>
#include <cstdio>
#include <algorithm>
#define REG(x, y) for (register int i = x; i <= y; ++i)
using namespace std;
struct Q
{
    int l, r, i, num;
}q[51000];
int n, m, k, len, sum, lal, lar;
int a[51000], c[51000], ans[51000];
bool cmp(Q x, Q y)
{
    return x.num == y.num ? x.num & 1 ? x.r < y.r : x.r > y.r : x.l < y.l;
}
int main()
{
    scanf("%d%d%d", &n, &m, &k);
    len = sqrt(n);
    REG(1, n) scanf("%d", &a[i]);
    REG(1, m)
    {
        q[i].i = i;
        scanf("%d%d", &q[i].l, &q[i].r);
        q[i].num = q[i].l / len;
    }
    sort(q + 1, q + m + 1, cmp);
    REG(q[1].l, q[1].r) sum += ((c[a[i]]++) << 1) | 1;
    ans[q[1].i] = sum;
    lal = q[1].l;
    lar = q[1].r;
    REG(1, m)
    {
        while (q[i].l < lal) sum += ((c[a[--lal]]++) << 1) | 1;
        while (q[i].r > lar) sum += ((c[a[++lar]]++) << 1) | 1;
        while (q[i].l > lal) sum -= ((--c[a[lal++]]) << 1) | 1;
        while (q[i].r < lar) sum -= ((--c[a[lar--]]) << 1) | 1;
        ans[q[i].i] = sum;
    }
    REG(1, m) printf("%d\n", ans[i]);
}

猜你喜欢

转载自www.cnblogs.com/xuyixuan/p/9580246.html