小B的询问 莫队分块




题目描述

小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。小B请你帮助他回答询问。

输入输出格式


输入格式:


第一行,三个整数N、M、K。

第二行,N个整数,表示小B的序列。

接下来的M行,每行两个整数L、R。


输出格式:


M行,每行一个整数,其中第i行的整数表示第i个询问的答案。

输入输出样例



输入样例#1: 复制

6 4 3 1 3 2 1 1 3 1 4 2 6 3 5 5 6



输出样例#1: 复制

6 9 5 2



说明

对于全部的数据,1<=N、M、K<=50000

 

莫队即可解决;

可参考[国家集训队]小Z的袜子



#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#include<cctype>
//#pragma GCC optimize(2)
using namespace std;
#define maxn 200005
#define inf 0x7fffffff
//#define INF 1e18
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
#define rdult(x) scanf("%lu",&x)
#define rdlf(x) scanf("%lf",&x)
#define rdstr(x) scanf("%s",x)
typedef long long  ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9 + 7;
#define Mod 1000000000
#define sq(x) (x)*(x)
#define eps 1e-3
typedef pair<int, int> pii;
#define pi acos(-1.0)
//const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef pair<int, int> pii;
inline ll rd() {
	ll x = 0;
	char c = getchar();
	bool f = false;
	while (!isdigit(c)) {
		if (c == '-') f = true;
		c = getchar();
	}
	while (isdigit(c)) {
		x = (x << 1) + (x << 3) + (c ^ 48);
		c = getchar();
	}
	return f ? -x : x;
}

ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a%b);
}
ll sqr(ll x) { return x * x; }

/*ll ans;
ll exgcd(ll a, ll b, ll &x, ll &y) {
	if (!b) {
		x = 1; y = 0; return a;
	}
	ans = exgcd(b, a%b, x, y);
	ll t = x; x = y; y = t - a / b * y;
	return ans;
}
*/

ll ans;
int n, m;
int c[maxn];
int pos[maxn];
ll sum[maxn];
ll Ans[maxn];
struct node {
	int l, r, id;

}nd[maxn];

bool cmpid(node a, node b) {
	return a.id < b.id;
}

bool cmp(node a, node b) {
	if (pos[a.l] == pos[b.l])return a.r < b.r;
	return a.l < b.l;
}

void init() {
	rdint(n); rdint(m); int K; rdint(K);
	for (int i = 1; i <= n; i++)rdint(c[i]);
	int blok = sqrt(n);
	for (int i = 1; i <= n; i++)pos[i] = (i - 1) / blok + 1;
	for (int i = 1; i <= m; i++) {
		rdint(nd[i].l); rdint(nd[i].r);
		nd[i].id = i;
	}

}

void add(int p, int val) {
	ans -= sqr(sum[c[p]]);
	sum[c[p]] += (ll)val;
	ans += sqr(sum[c[p]]);
}

void sol() {
	for (int i = 1, l = 1, r = 0; i <= m; i++) {
		for (; r < nd[i].r; r++)add(r + 1, 1);
		for (; r > nd[i].r; r--)add(r, -1);
		for (; l < nd[i].l; l++)add(l, -1);
		for (; l > nd[i].l; l--)add(l - 1, 1);
		Ans[nd[i].id] = ans;
	}
}

int main() {
	//ios::sync_with_stdio(0);
	init();
	sort(nd + 1, nd + 1 + m, cmp);
	sol();
	sort(nd + 1, nd + 1 + m, cmpid);
	for (int i = 1; i <= m; i++) {
		printf("%lld\n", Ans[nd[i].id]);
	}
	return 0;
}