【BZOJ3781】小B的询问【莫队算法】

【题目链接】

不会什么考什么,赶紧学发莫队。

/* Telekinetic Forest Guard */
#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long LL;

const int maxn = 50005, sqrtn = 223;

int n, m, k, num[maxn], cnt[maxn];
LL ans, res[maxn];

struct _query {
	int l, r, id;

	bool operator < (const _query &x) const {
		int a = l / sqrtn, b = x.l / sqrtn;
		if(a != b) return a < b;
		return r < x.r;
	}
} que[maxn];

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

inline void add(int x) {
	ans -= cnt[num[x]] * cnt[num[x]];
	cnt[num[x]]++;
	ans += cnt[num[x]] * cnt[num[x]];
}

inline void del(int x) {
	ans -= cnt[num[x]] * cnt[num[x]];
	cnt[num[x]]--;
	ans += cnt[num[x]] * cnt[num[x]];
}

int main() {
	n = iread(); m = iread(); k = iread();
	for(int i = 1; i <= n; i++) num[i] = iread();
	for(int i = 1; i <= m; i++) que[i] = (_query){iread(), iread(), i};

	sort(que + 1, que + 1 + m);

	int l = 1, r = 0;
	for(int i = 1; i <= m; i++) {
		while(que[i].l < l) add(--l);
		while(r < que[i].r) add(++r);
		while(l < que[i].l) del(l++);
		while(que[i].r < r) del(r--);
		res[que[i].id] = ans;
	}

	for(int i = 1; i <= m; i++) printf("%lld\n", res[i]);
	return 0;
}


你可能感兴趣的:(【BZOJ3781】小B的询问【莫队算法】)