Yandex.Algorithm 2011 Round 2 D. Powerful array(莫队算法)

题意:给出一个由n个正整数形成的数组,t次询问,每次询问一个区间[l,r]内所有ks^2*s的和,ks为数s在区间内出现的次数。

莫队算法讲解传送门:莫队算法详解

个人觉得这个pdf讲得还是比较容易懂的,内附模版,修改一下add和remove酒很容易可以过这道题了。

另外,需要注明的是,用__int64开数组会爆内存,用longlong才可以,表示很无语。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;

typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=200005;
int n,t;
int a[maxn],cnt[1000005];
int currentL,currentR;
ll ans[maxn];
ll Ans;

struct Node{
	int l;
	int r;
	int block;
	int id;
	bool operator < (const Node &a) const {
		return (block<a.block)||(block==a.block&&r<a.r);
	}
}node[maxn];

void add(int pos){
	Ans=Ans+(2*cnt[a[pos]]+1)*a[pos];
	cnt[a[pos]]++;
}

void remove(int pos){
	Ans=Ans-(2*cnt[a[pos]]-1)*a[pos];
	cnt[a[pos]]--;
}

int main(){
	scanf("%d%d",&n,&t);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		int block_size=sqrt(n);
		for(int i=1;i<=t;i++) {
			scanf("%d%d",&node[i].l,&node[i].r);
			node[i].block=node[i].l/block_size;
			node[i].id=i;
		}
		sort(node+1,node+t+1);
		memset(cnt,0,sizeof(cnt));
		currentL=currentR=0,Ans=0;
		for(int i=1;i<=t;i++){
			while(currentL<node[i].l) remove(currentL),currentL++;
			while(currentL>node[i].l) add(currentL-1),currentL--;
			while(currentR<node[i].r) add(currentR+1),currentR++;
			while(currentR>node[i].r) remove(currentR),currentR--;
			ans[node[i].id]=Ans;
		}
		for(int i=1;i<=t;i++) printf("%I64d\n",ans[i]);
	return 0;
}


你可能感兴趣的:(Yandex.Algorithm 2011 Round 2 D. Powerful array(莫队算法))