[BZOJ3781]: ask the small B (Mo teams algorithm)

Topic Portal


Title Description

B has a small sequence contains an integer number between $ N $ $ 1 ~ K $. He asks a total of $ M $, each interrogation a given interval $ [L ... R] $, seeking $ \ sum \ limits_ {i = 1} ^ {K} c (i) ^ 2 value of $ , where $ c (i) $ $ I $ represents a number in the $ [L ... R] $ the number of repetitions. Small $ B $ invite you to help him answer questions.


Input Format

The first row, three integers N, M, K.
Second row, N integers, B represents a sequence of small.
The next M rows, each row two integers L, R.


Output Format

M lines, each an integer, wherein the integer represents the i-th row of the i-th answer inquiries.


Sample

Sample input

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

Sample Output

6
9
5
2


Data range and tips

For all data, $ 1 \ leqslant N, M, K \ leqslant 50,000 $.


answer

Happy to discover that requires offline, and the data in the range of $ $ 50,000, more relaxed, so consider Mo team.

First sequence block, and then ask the sort, constantly stretching around the endpoint, be careful not to mistake enough.

I really do not know what to say anymore ......


Code time

#include<bits/stdc++.h>
using namespace std;
struct rec
{
	int id;
	int l;
	int r;
	int pos;
}q[50001];
int a[50001];
int cnt[50001];
long long ans;
long long sum[50001];
bool cmp(rec a,rec b){return a.pos==b.pos?a.r<b.r:a.pos<b.pos;}//排序
int main()
{
	int n,m,k;
	scanf("%d%d%d",&n,&m,&k);
	int t=sqrt(n);//分块
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&q[i].l,&q[i].r);
		q[i].id=i;
		q[i].pos=(q[i].l-1)/t+1;
	}
	sort(q+1,q+m+1,cmp);
	int l=1,r=0;
	for (int i = 1; i <= m; i ++) // about four cases telescopic endpoint 
	{ 
		the while (L <Q [I] .L) 
		{ 
			ans- CNT = 2 * [A [L]] -. 1; // Note that the answer subtraction 
			CNT [a [L]] -; 
			L ++; 
		} 
		the while (L> Q [I] .L) 
		{ 
			l - the; 
			ANS CNT + = 2 * [a [L]] +. 1; 
			CNT [A [L]] ++; 
		} 
		the while (R & lt <Q [I] .r) 
		{ 
			R & lt ++; 
			ANS CNT + = 2 * [A [R & lt]] +. 1; 
			CNT [A [R & lt]] ++; 
		} 
		the while (R & lt> Q [I] .r) 
		{ 
			ans- CNT = 2 * [A [R & lt]] -. 1; 
			CNT [A [R & lt]] -; 
			r--; 
		} 
		SUM [Q [I] .id ] = ANS; 
	} 
	for (int I =. 1; I <= m; I ++) 
		the printf ( "% LLD \ n-", SUM [I]); 
	return 0;
}

rp ++

Guess you like

Origin www.cnblogs.com/wzc521/p/11239470.html