「树状数组」[SDOI2009]HH的项链
Posted nicoppa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「树状数组」[SDOI2009]HH的项链相关的知识,希望对你有一定的参考价值。
[SDOI2009]HH的项链
原题链接 [SDOI2009]HH的项链
题目大意
给你 \(n\) 个数,再给你 \(q\) 次询问,每次询问给你 \(l, r\) ,问你 \(l, r\) 中有多少个不同的数
题目题解
分析这道题我们发现,对于一个 \([L_1, R_1]\) 存在另一个 \([L_2, R_1]\) 且 \(L_2\) 严格大于 \(L_1\),那么就一定存在第一个区间不同的数 大于等于 第二个区间的不同的数,这里很显然有一种等于的情况,什么情况等于?在\([L_2,R_1]\) 中包含的数与 \([L_1, L_2 - 1]\) 中包含的数 ,后者的数前者都有。那么我们就发现 对于这样的情况\([L_1, L_2 - 1]\) 中就没有必要存在了。但注意的是,这里我们是严格定义的 \(R_1\)相同 且\(L_1 < L_2\),我们继续推发现\(R_2 > R_1\) 也是符合条件的。
于是我们得到若我们按查询的右区间从小到大排序,这样的就能转化为一个线性的前缀和问题,我们用数据结构来维护每一位上是否为1或0,若为1则说明之后没出现相同的数,若为1则说明出现过,每次处理到查询位的\(R\),然后用数据结构查询 \(sum_R - sum_l - 1\) 的值,就能得到我们的答案了
我们这里用树状数组维护,代码如下
//#define fre yes
#include <cstdio>
#include <algorithm>
const int N = 1000005;
struct Node
int l, r;
int pos;
w[N];
int Vis[N], arr[N], ans[N];
int tree[N];
bool cmp(Node x, Node y)
return x.r < y.r;
int lowbit(int x)
return x & (-x);
int n;
void change(int x, int k)
while(x <= n)
tree[x] += k;
x += lowbit(x);
int sum(int x)
int res = 0;
while(x > 0)
res += tree[x];
x -= lowbit(x);
return res;
int main()
static int q;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &arr[i]);
scanf("%d", &q);
for (int i = 1; i <= q; i++)
int l, r;
scanf("%d %d", &l, &r);
w[i].l = l; w[i].r = r;
w[i].pos = i;
std::sort(w + 1, w + 1 + q, cmp);
int tot = 1;
for (int i = 1; i <= q; i++)
for (int j = tot; j <= w[i].r; j++)
if(Vis[arr[j]]) change(Vis[arr[j]], -1);
change(j, 1);
Vis[arr[j]] = j;
tot = w[i].r + 1;
ans[w[i].pos] = sum(w[i].r) - sum(w[i].l - 1);
for (int i = 1; i <= q; i++)
printf("%d\n", ans[i]);
return 0;
以上是关于「树状数组」[SDOI2009]HH的项链的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj1878] [SDOI2009]HH的项链(树状数组+离线)
BZOJ1878: [SDOI2009]HH的项链[树状数组 离线]