「解题报告」P1972 HH的项链
题目链接:HH的项链
这道题做法很多,看到有用线段树,主席树和莫队做的,但我不太会用树状数组,所以讲解一下树状数组的解法。
题干告诉我们要求区间内的贝壳的种类数,那么用树状数组怎么维护呢?我们通过一个简单的例子来理解一下。对于一个序列:1 4 3 2 4 2
,我们要去求这个序列里的贝壳的个数,我们就要考虑去重,将这个序列变为1 4 3 2 0 0
,这样就代表了
但是我们会发现一个问题,就是这样处理的话我们要想求2
,但实际上的答案应该是3
,那么我们就可以把某一区间内比较靠后的贝壳,作为这一区间内这种贝壳出现的唯一次数,然后记录一下上一个同种贝壳出现的位置,更新传递一下即可。具体做法就是将询问区间的操作离线,按右端点的大小进行排序,然后一一枚举贝壳的数量即可。
代码实现:
点击查看代码
#define lowbit(x) x & (-x)
using namespace std;
const int M = 1e6 + 10;
struct node {
int l, r, id;
friend bool operator<(node x1,node x2) {
if (x1.r == x2.r) return x1.l < x2.l;
return x1.r < x2.r;
}
} plan[M];
int n, m, k=1;
int a[M], p[M], ans[M], c[M];
void add(int x, int val) {
for (int i = x; i <= n; i += lowbit(i))
c[i] += val;
}
int query(int x) {
int res = 0;
for (int i = x; i; i -= lowbit(i))
res += c[i];
return res;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
cin >> m;
for (int i = 1; i <= m; i++)
{
cin >> plan[i].l >> plan[i].r;
plan[i].id = i;
}
sort(plan + 1, plan + 1 + m);
for (int i = 1; i <= plan[m].r; i++) {
if (!p[a[i]]) {
p[a[i]] = i;
add(i, 1);
} else {
add(p[a[i]], -1);
p[a[i]] = i;
add(p[a[i]], 1);
}
while (i == plan[k].r) {
ans[plan[k].id] = query(plan[k].r) - query(plan[k].l-1);
k++;
}
}
for (int i = 1; i <= m; i++)
cout << ans[i] << '\n';
return 0;
}
作者:Aewrxuk
出处:https://www.cnblogs.com/Aewrxuk/p/17644033.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)