[Codeforces86D]Powerful array(莫队算法)

题意:定义K[x]为元素x在区间[l,r]内出现的次数,那么它的贡献为K[x]*K[x]*x

给定一个序列,以及一些区间询问,求每个区间的贡献

算是莫队算法膜版题,不带修改的

Code

#include <cstdio>
#include <algorithm>
#include <cmath>
#define N 200010
#define ll long long
using namespace std;

int n,m,A[N],bl[N],k[N*5];
ll sum,Ans[N];
struct info{
	int l,r,id;
	friend bool operator <(info a,info b){
		return (bl[a.l]==bl[b.l])?a.r<b.r:a.l<b.l;
	}
}q[N];

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

void upd(int x,int d){
	sum-=k[A[x]]*1ll*k[A[x]]*A[x];
	k[A[x]]+=d;
	sum+=k[A[x]]*1ll*k[A[x]]*A[x];
}

int main(){
	n=read(),m=read();int blo=sqrt(n);
	for(int i=1;i<=n;++i) A[i]=read(),bl[i]=i/blo+1;
	for(int i=1;i<=m;++i) q[i].l=read(),q[i].r=read(),q[i].id=i;
	sort(q+1,q+m+1);
	for(int i=1,l=1,r=0;i<=m;++i){
		for(;l<q[i].l;++l) upd(l,-1);
		for(;l>q[i].l;--l) upd(l-1,1);
		for(;r<q[i].r;++r) upd(r+1,1);
		for(;r>q[i].r;--r) upd(r,-1);
		Ans[q[i].id]=sum;
	}
	for(int i=1;i<=m;printf("%lld
",Ans[i++]));
	return 0;
}
原文地址:https://www.cnblogs.com/void-f/p/9090472.html