【莫队】小B的询问

版权声明:转载者乖乖♂站好 https://blog.csdn.net/Eric1561759334/article/details/82941520

题目

https://www.luogu.org/problemnew/show/P2709

思路

莫队经典例题

这题询问每一种数字数量的平方和,那么我们在左移或右移的时候记录一下就好了,当每一种数字的种类数加1或减1的时候,我们需要减去以前这个数对答案的影响,加上现在对答案的影响。

假设原来数字a的种类数为k,如今又加入一个a,那么先ans-=k2,然后ans+=(k+1)2.,删除同理。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=5e4+77;
int b[maxn],t[maxn],n,m,k,len;;
long long ans[maxn],s;
struct node
{
	int l,r,id,d;
}a[maxn];
bool cmp(node a,node b)
{
	return a.id<b.id||a.id==b.id&&a.r<b.r;
}
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	len=sqrt(n);
	for(int i=1;i<=n;i++) scanf("%d",&b[i]);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&a[i].l,&a[i].r);
		a[i].id=(a[i].l+len-1)/len;
		a[i].d=i;
	}
	sort(a+1,a+m+1,cmp);
	int l=a[1].l;
	int r=a[1].l-1;
	for(int i=1;i<=m;i++)
	{
		while(l<a[i].l) s-=2*--t[b[l++]]+1;
		while(l>a[i].l) s+=2*++t[b[--l]]-1;
		while(r>a[i].r) s-=2*--t[b[r--]]+1;
		while(r<a[i].r) s+=2*++t[b[++r]]-1;
		ans[a[i].d]=s;
	}
	for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
	return 0; 
}

猜你喜欢

转载自blog.csdn.net/Eric1561759334/article/details/82941520
今日推荐