拥挤的甜蜜小屋
0.题意简述
多组询问,每个询问求 c a r d ( { a [ i ] ∣ i ∈ [ l , r ] } ) card (\{a[i] | i \in [l, r]\}) card({a[i]∣i∈[l,r]})。
1.前言
妙啊
第一眼看过去,马上想到莫队,正想嘲讽出题人,结果一看数据范围
n
,
q
≤
1
0
6
n, q \leq 10^6
n,q≤106,马上就傻眼了。
2.
莫队时间复杂度起飞了,只得换种算法。由于 ta 是与权值挂钩,所以我们自然想到从权值入手(权值线段树),如果遇到两个相同元素怎么办?选下标靠前的还是下标靠后的?
如果我们的询问区间按照右端点递增排序,则我们一定选择下标靠后的(不超过区间右端点),因为下标靠前的在区间内,则下标靠后的在区间内。
所以我们离线记录询问,按照询问区间右端点递增排序,用权值线段树(树状数组同理)记录下对于每一个值 x x x 最后出现的下标 i i i,统计答案时用下标小于等于 r r r 的个数剪去下标小于等于 l − 1 l - 1 l−1 的个数即可。
这里用的是树状数组(因为短)
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
template <typename T>
void read (T &x) {
x = 0; T f = 1;
char ch = getchar ();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar ();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar ();
}
x *= f;
}
template <typename T>
void write (T x) {
if (x < 0) {
x = -x;
putchar ('-');
}
if (x < 10) {
putchar (x + '0');
return;
}
write (x / 10);
putchar (x % 10 + '0');
}
template <typename T>
void print (T x, char ch) {
write (x); putchar (ch);
}
const int Maxn = 1e6;
const int Maxa = 4 * 1e3;
int n, m;
int a[Maxn + 5], last[Maxa + 5], ans[Maxn + 5];
struct sec {
int l, r, id;
}b[Maxn + 5];
bool cmp (sec x, sec y) {
return x.r < y.r;
}
struct Array {
int BIT[Maxn + 5];
int lowbit (int x) { return x & -x; }
void Update (int Index, int x) {
Index++;
for (int i = Index; i <= Maxn; i += lowbit (i)) {
BIT[i] += x;
}
}
int Query (int Index) {
Index++;
int res = 0;
for (int i = Index; i >= 1; i -= lowbit (i)) {
res += BIT[i];
}
return res;
}
}tr;
int main () {
read (n); read (m);
for (int i = 1; i <= n; i++)
read (a[i]);
for (int i = 1; i <= m; i++)
read (b[i].l), read (b[i].r), b[i].id = i;
sort (b + 1, b + 1 + m, cmp);
int poi = 1;
for (int i = 1; i <= n; i++) {
if (last[a[i]] != 0)
tr.Update (last[a[i]], -1);
last[a[i]] = i;
tr.Update (last[a[i]], 1);
while (poi <= m && b[poi].r == i) {
ans[b[poi].id] = tr.Query (i) - tr.Query (b[poi].l - 1);
poi++;
}
}
for (int i = 1; i <= m; i++) {
print (ans[i], '\n');
}
return 0;
}