bzoj 2743 [HEOI2012]采花 离线处理+树状数组
题面
解法
记\(nxt_i\)为\(a_i\)下一次出现的位置
把所有询问按左端点排序
处理完所有以\(i\)开始的询问后,我们把\(nxt_i\)的影响删除,把\(nxt_{nxt_i}\)加上
这样就能保证计算入答案的必然是这个区间里第二次出现的
树状数组维护即可
时间复杂度:\(O(q\ log\ q+q\ log\ n)\)
代码
#include <bits/stdc++.h>
#define N 2000010
using namespace std;
template <typename node> void read(node &x) {
x = 0; int f = 1; char c = getchar();
while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
struct Node {
int l, r, id;
bool operator < (const Node &a) const {
return l < a.l;
}
} b[N];
int n, c, q, a[N], f[N], s[N], ans[N], las[N], nxt[N], tmp[N];
int lowbit(int x) {return x & -x;}
void modify(int x, int val) {
for (int i = x; i <= n; i += lowbit(i))
f[i] += val;
}
int query(int x) {
int ret = 0;
for (int i = x; i; i -= lowbit(i)) ret += f[i];
return ret;
}
int main() {
read(n), read(c), read(q);
for (int i = 1; i <= n; i++) read(a[i]);
for (int i = n; i; i--) nxt[i] = las[a[i]], las[a[i]] = i;
for (int i = 1; i <= c; i++)
if (nxt[las[i]]) modify(nxt[las[i]], 1);
for (int i = 1; i <= q; i++) read(b[i].l), read(b[i].r), b[i].id = i;
sort(b + 1, b + q + 1); int now = 1;
for (int i = 1; i <= q; i++) {
while (now < b[i].l) {
if (nxt[now]) modify(nxt[now], -1);
if (nxt[nxt[now]]) modify(nxt[nxt[now]], 1);
now++;
}
ans[b[i].id] = query(b[i].r) - query(b[i].l - 1);
}
for (int i = 1; i <= q; i++) cout << ans[i] << "\n";
return 0;
}