https://www.luogu.com.cn/problem/P2709#submit
小B的询问
题目描述
小B 有一个长为 \(n\) 的整数序列 \(a\),值域为 \([1,k]\)。
他一共有 \(m\) 个询问,每个询问给定一个区间 \([l,r]\),求:
其中 \(c_i\) 表示数字 \(i\) 在 \([l,r]\) 中的出现次数。
小B请你帮助他回答询问。
输入格式
第一行三个整数 \(n,m,k\)。
第二行 \(n\) 个整数,表示 小B 的序列。
接下来的 \(m\) 行,每行两个整数 \(l,r\)。
输出格式
输出 \(m\) 行,每行一个整数,对应一个询问的答案。
样例 #1
样例输入 #1
6 4 3
1 3 2 1 1 3
1 4
2 6
3 5
5 6
样例输出 #1
6
9
5
2
提示
【数据范围】
对于 \(100\%\) 的数据,\(1\le n,m,k \le 5\times 10^4\)。
//标准莫队板子
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n, m, k, block;
int l = 1, r = 0, out[5211314], ans;
int a[5211314], pos[5211314], cnt[5211314];
struct ASK {
int l, r, id;
}ask[5211314];
inline bool cmp(ASK a, ASK b) {
if (pos[a.l] != pos[b.l]) return pos[a.l] < pos[b.l];
else return a.r < b.r;
}
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 << 1) + (x << 3) + (ch - '0');
ch = getchar();
}
return x * f;
}
inline void Add(int x) {
ans = ans + 2 * cnt[x] * 1 + 1;
cnt[x] ++;
return;
}
inline void Del(int x) {
ans = ans - 2 * cnt[x] * 1 + 1;
cnt[x] --;
return;
}
int main() {
n = read();
m = read();
k = read();
block = sqrt(n);
for (int i = 1; i <= n; ++ i) {
a[i] = read();
pos[i] = (i - 1) / block + 1;
}
for (int i = 1; i <= m; ++ i) {
ask[i].l = read();
ask[i].r = read();
ask[i].id = i;
}
sort(ask + 1, ask + 1 + m, cmp);
for (int i = 1; i <= m; ++ i) {
while (ask[i].l < l) Add(a[-- l]);
while (l < ask[i].l) Del(a[l ++]);
while (r < ask[i].r) Add(a[++ r]);
while (ask[i].r < r) Del(a[r --]);
out[ask[i].id] = ans;
}
for (int i = 1; i <= m; ++ i) {
printf("%d\n", out[i]);
}
return 0;
}
标签:ch,int,Luogu,询问,pos,P2709,include,5211314
From: https://www.cnblogs.com/jueqingfeng/p/17458485.html