[BZOJ3781]小B的询问
[BZOJ3781]小B的询问
试题描述
小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。小B请你帮助他回答询问。
输入
第一行,三个整数N、M、K。
第二行,N个整数,表示小B的序列。
接下来的M行,每行两个整数L、R。
输出
M行,每行一个整数,其中第i行的整数表示第i个询问的答案。
输入示例
6 4 3 1 3 2 1 1 3 1 4 2 6 3 5 5 6
输出示例
6 9 5 2
数据规模及约定
对于全部的数据,1<=N、M、K<=50000
题解
莫队裸题。。。
就我的莫队跑得慢(大概是因为用了 vector?)。。。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
#define maxn 50010
#define maxbl 233
#define LL long long
int A[maxn];
struct Que {
int l, r;
Que() {}
Que(int _, int __): l(_), r(__) {}
} qs[maxn];
bool cmp(int a, int b) { return qs[a].r < qs[b].r; }
vector <int> qid[maxbl];
int tot[maxn];
LL Ans[maxn];
LL sqr(int x) { return (LL)x * x; }
int main() {
int n = read(), q = read(), K = read();
for(int i = 1; i <= n; i++) A[i] = read();
int m = sqrt(n + .5), cntb = 0;
for(int i = 1; i <= q; i++) {
int l = read(), r = read();
qs[i] = Que(l, r);
qid[(l-1)/m+1].push_back(i);
cntb = max(cntb, (l - 1) / m + 1);
}
for(int i = 1; i <= cntb; i++) {
sort(qid[i].begin(), qid[i].end(), cmp);
memset(tot, 0, sizeof(tot));
int l = 1, r = 0; LL ans = 0;
for(vector <int> :: iterator j = qid[i].begin(); j != qid[i].end(); j++) {
while(r < qs[*j].r) tot[A[++r]]++, ans = ans - sqr(tot[A[r]] - 1) + sqr(tot[A[r]]);
while(l < qs[*j].l) tot[A[l]]--, ans = ans - sqr(tot[A[l]] + 1) + sqr(tot[A[l]]), l++;
while(l > qs[*j].l) tot[A[--l]]++, ans = ans - sqr(tot[A[l]] - 1) + sqr(tot[A[l]]);
Ans[*j] = ans;
}
}
for(int i = 1; i <= q; i++) printf("%lld\n", Ans[i]);
return 0;
}

浙公网安备 33010602011771号