笔记-CF220B Little Elephant and Array
与 SDOI2009 HH的项链、CF351D Jeff and Removing Periods 类似的套路。
每次想到要用莫队前可以先想想:能不能把询问挂到右端点离线处理!
对于每个颜色,如果它 \(\le n\),用 vector
存下它的出现位置。
枚举到 \(i\) 的时候,如果 \(a_i\) 已经有 \(a_i\) 个了,如果以 \(i\) 为右端点,在树状数组上满足条件的位置区间 \(+1\)。
如果 \(>a_i\) 个了,还要把之前的区间减掉。
然后对于每个询问单点查询即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define x first
#define y second
#define bg begin()
#define ed end()
#define pb push_back
#define mp make_pair
#define sz(a) int((a).size())
#define R(i,n) for(int i(0);i<(n);++i)
#define L(i,n) for(int i((n)-1);i>=0;--i)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;
//ReadWrite
const int BUF=1<<20;
static char buf[BUF],*p1=buf,*p2=buf,obuf[BUF],*p3=obuf;
// #define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,BUF,stdin),p1==p2)?EOF:*p1++
// #define putchar(x) (p3-obuf<BUF)?(*p3++=x):(fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=x)
template<typename item>void read(item &x){
x=0; item f=1; char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
x*=f;
}
template<typename item>void write(item x){
if(x<0) x=-x,putchar('-');
if(x>9) write(x/10); putchar(((x%10)^48));
}
struct Flusher{~Flusher(){fwrite(obuf,p3-obuf,1,stdout);}}flusher;
//Data
const int N=1e5;
int n,m,a[N],ns[N];
vector<pair<int,int>> ask[N];
vector<int> col[N];
//FenwickTree
int fen[N];
void add(int i,int v){for(;i<n;i|=i+1) fen[i]+=v;}
int sum(int i,int v=0){for(;~i;(i&=i+1)--) v+=fen[i]; return v;}
//Main
int main(){
read(n),read(m);
R(i,n) read(a[i]),--a[i];
R(i,n) col[i].pb(-1);
R(i,m){
int l,r; read(l),read(r),--l,--r;
ask[r].pb(mp(l,i));
}
R(i,n){
if(a[i]<n){
vector<int> &c=col[a[i]];
if(sz(c)>=a[i]+2) add(c[sz(c)-a[i]-2]+1,-1),
add(c[sz(c)-a[i]-1]+1,1); c.pb(i);
if(sz(c)>=a[i]+2) add(c[sz(c)-a[i]-2]+1,1),
add(c[sz(c)-a[i]-1]+1,-1);
}
for(const pair<int,int> &u:ask[i]) ns[u.y]=sum(u.x);
}
R(i,m) cout<<ns[i]<<'\n';
return 0;
}