题目链接
入门级的莫队,网上的题解都是结合离散化,在我看了其实是画蛇添足。因为当一个x是大于1e5时,他是不可能构成出现x次的(因为n<=1e5),这个咱们只要return掉,不用管就行了。这里保险起见开得1e6。我们定义为i出现的个数。
比较容易使用莫队转移状态。
下面是ac代码:
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <map>
#define ll long long
using namespace std;
const int N = 1e5+5;
ll c[N];
ll sum[N];
map<int, int> mp;
struct Node
{
ll l, r, id;
}q[N];
ll anss[N];
ll block;
ll ans = 0;
int gg[N*10];
bool cmp(Node a, Node b)
{
return (a.r / block == b.r /block) ? a.l < b.l:a.r < b.r;
}
void del (int x)
{
if (c[x] > 1e6) return;
gg[c[x]]--;
if (gg[c[x]] == c[x]) ans++;
else if (gg[c[x]] == c[x]-1) ans--;
}
void add(int x)
{
if (c[x] > 1e6) return;
gg[c[x]]++;
if (gg[c[x]] == c[x]) ans++;
else if (gg[c[x]] == c[x]+1) ans--;
}
int main()
{
ll n, m, k;
scanf("%lld%lld", &n, &m);
block = sqrt(n);
for (int i = 1; i <= n; i++)
scanf("%lld", &c[i]);
for (int i = 1; i <= m; i++)
{
scanf("%lld%lld", &q[i].l, &q[i].r);
q[i].id = i;
}
sort(q+1, q+m+1, cmp);
int l = 1, r = 0;
for (int i = 1; i <= m; i++)
{
ll ql = q[i].l, qr = q[i].r;
while(l < ql) del(l++);
while(l > ql) add(--l);
while(r < qr) add(++r);
while(r > qr) del(r--);
anss[q[i].id] = ans;
}
for (int i = 1; i <= m; i++)
printf("%lld\n", anss[i]);
return 0;
}