題目鏈接
入門級的莫隊,網上的題解都是結合離散化,在我看了其實是畫蛇添足。因爲當一個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;
}