洛谷 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]);
}
posted @ 2018-09-03 18:51  xuyixuan  阅读(124)  评论(0编辑  收藏  举报