题目大意:一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。
思路:莫队走起。
CODE:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 50010
using namespace std;
int belong[MAX],block_size;
struct Ask{
int x,y,id;
bool operator <(const Ask &a)const {
if(belong[x] == belong[a.x]) return y <= a.y;
return belong[x] < belong[a.x];
}
void Read(int p) {
scanf("%d%d",&x,&y);
id = p;
belong[p] = p / block_size;
}
}ask[MAX];
int cnt,asks;
int src[MAX];
int v[MAX],now;
int ans[MAX];
int main()
{
cin >> cnt >> asks;
scanf("%*d");
block_size = sqrt(cnt);
for(int i = 1; i <= cnt; ++i)
scanf("%d",&src[i]);
for(int i = 1; i <= asks; ++i)
ask[i].Read(i);
sort(ask + 1,ask + asks + 1);
int l = 1,r = 0;
for(int temp,i = 1; i <= asks; ++i) {
while(r < ask[i].y) {
temp = src[++r];
now -= v[temp] * v[temp];
++v[temp];
now += v[temp] * v[temp];
}
while(l > ask[i].x) {
temp = src[--l];
now -= v[temp] * v[temp];
++v[temp];
now += v[temp] * v[temp];
}
while(l < ask[i].x) {
temp = src[l++];
now -= v[temp] * v[temp];
--v[temp];
now += v[temp] * v[temp];
}
while(r > ask[i].y) {
temp = src[r--];
now -= v[temp] * v[temp];
--v[temp];
now += v[temp] * v[temp];
}
ans[ask[i].id] = now;
}
for(int i = 1; i <= asks; ++i)
printf("%d\n",ans[i]);
return 0;
}原文地址:http://blog.csdn.net/jiangyuze831/article/details/41549303