3809: Gty的二逼妹子序列
分析:
和这道AHOI2013 作业差不多。权值是1~n的,所以对权值进行分块。$O(1)$修改,$O(\sqrt n)$查询。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ; int bel[N], sum[N], a[N], Ans[N * ], cnt[N], B;
struct Que{
int l, r, a, b, id;
bool operator < (const Que &A) const {
return bel[l] == bel[A.l] ? r < A.r : bel[l] < bel[A.l];
}
}Q[N * ]; inline void add(int x) {
cnt[x] ++;
if (cnt[x] == ) sum[bel[x]] ++;
}
inline void del(int x) {
cnt[x] --;
if (cnt[x] == ) sum[bel[x]] --;
}
inline int query(int l,int r) {
int res = ;
for (int i = l, lim = min(r, bel[l] * B); i <= lim; ++i) res += (cnt[i] > );
if (bel[l] != bel[r])
for (int i = (bel[r] - ) * B + ; i <= r; ++i) res += (cnt[i] > );
for (int i = bel[l] + ; i <= bel[r] - ; ++i) res += sum[i];
return res;
}
int main() {
int n = read(), m = read(); B = sqrt(n);
for (int i = ; i <= n; ++i) a[i] = read();
for (int i = ; i <= m; ++i)
Q[i].l = read(), Q[i].r = read(), Q[i].a = read(), Q[i].b = read(), Q[i].id = i;
for (int i = ; i <= n; ++i) bel[i] = (i - ) / B + ;
sort(Q + , Q + m + );
int L = , R = ;
for (int i = ; i <= m; ++i) {
while (L > Q[i].l) add(a[--L]);
while (R < Q[i].r) add(a[++R]);
while (L < Q[i].l) del(a[L++]);
while (R > Q[i].r) del(a[R--]);
Ans[Q[i].id] = query(Q[i].a, Q[i].b);
}
for (int i = ; i <= m; ++i) printf("%d\n",Ans[i]);
return ;
}