P1972 [SDOI2009]HH的项链

声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。

题目描述

\(HH\) 有一串由各种漂亮的贝壳组成的项链。\(HH\) 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。\(HH\) 不断地收集新的贝壳,因此,他的项链变得越来越长。

有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答…… 因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。

输入格式

一行一个正整数 \(n\) ,表示项链长度。

第二行 \(n\) 个正整数 \(a_i\) ,表示项链中第 \(i\) 个贝壳的种类。

第三行一个整数 \(m\),表示 \(H\) 询问的个数。

接下来 \(m\) 行,每行两个整数 \(l,r\) 表示询问的区间。

输出格式

输出 \(m\) 行,每行一个整数,依次表示询问对应的答案。


Solution

首先贴一下我觉得写得非常清楚的题解,以下转载自这篇题解:

"这个题用树状数组,线段树等等都可以做,不过用树状数组写起来更方便。

此题首先应考虑到这样一个结论:

对于若干个询问的区间 \([l,r]\),如果他们的r都相等的话,那么项链中出现的同一个数字,一定是只关心出现在最右边的那一个的,例如:

项链是:\(1 \ 3 \ 4 \ 5 \ 1\)

那么,对于 \(r=5\) 的所有的询问来说,第一个位置上的 \(1\) 完全没有意义,因为 \(r\) 已经在第五个 \(1\) 的右边,对于任何查询的 \([L,5]\) 区间来说,如果第一个 \(1\) 被算了,那么他完全可以用第五个 \(1\) 来替代。

因此,我们可以对所有查询的区间按照 \(r\) 来排序,然后再来维护一个树状数组,这个树状数组是用来干什么的呢?看下面的例子:

\(1 \ 2 \ 1 \ 3\)

对于第一个 \(1\),\(insert(1,1)\);表示第一个位置出现了一个不一样的数字,此时树状数组所表示的每个位置上的数字(不是它本身的值而是它对应的每个位置上的数字)是:\(1 \ 0 \ 0 \ 0\)

对于第二个 \(2\),\(insert(2,1)\);此时树状数组表示的每个数字是 \(1 \ 1 \ 0 \ 0\)

对于第三个 \(1\),因为之前出现过 \(1\) 了,因此首先把那个 \(1\) 所在的位置删掉 \(insert(1,-1)\),然后在把它加进来 \(insert(3,1)\) 。此时每个数字是\(0 \ 1 \ 1 \ 0\)

如果此时有一个询问 \([2,3]\),那么直接求 \(sum(3)-sum(2-1)=2\)就是答案。

题解清楚么?"

看完之后觉得,哇,这道题也就这样嘛,不难啊。可是为什么我接触树状数组一个多学期了,这样基础的题目都想不到,运用不好呢?

一个数据结构,最重要的就是运用,于是借这道题简单理顺一下树状数组。

树状数组支持以下:

\(1.\) 单点修改

\(2.\) 区间修改(维护差分)

\(3.\) 单点查询

\(4.\) 前缀查询

\(5.\) 区间查询(实际上是前缀的运用)

所以,碰到一道数据结构的题,若它可以通过发现本题的某些特殊性质,进而转化为和 前缀和、区间和 有关的问题,那么就可以尝试用树状数组做。

例如这道题,经过观察后(\(ps:\) 这个观察往往也是非常非常重要的,一般来说可以多手算几组合适的样例)发现区间的变动非常不好处理,那么我们就把 \(r\) 相等的区间分为一组来考虑,再排序,进一步发现种类数只和最靠近 \(r\) 的有关,从而转化为一个动态求区间值的问题。


Code

#include<cstdio>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cmath>
#include<cstring>
#define lowbit(x) x & -x
#define F(i, x, y) for(int i = x; i <= y; ++ i)
using namespace std;
int read();
const int N = 1e6 + 5;
int n, q;
int a[N];
int tree[N];
int last[N];
struct node{
int l, r, num, ans;
}k[N];
bool cmp1(node x, node y){ return x.r < y.r;}
bool cmp2(node x, node y){ return x.num < y.num;}
void add(int pos, int v)
{
for(; pos <= n; pos += lowbit(pos)) tree[pos] += v;
}
int getsum(int pos)
{
int res = 0;
for(; pos; pos -= lowbit(pos)) res += tree[pos];
return res;
}
int main()
{
n = read();
F(i, 1, n) a[i] = read();
q = read();
F(i, 1, q) k[i].l = read(), k[i].r = read(), k[i].num = i;
sort(k + 1, k + 1 + q, cmp1);
F(i, 1, q)
{
if(k[i].r != k[i - 1].r)
F(j, k[i - 1].r + 1, k[i].r)
{
if(last[a[j]]) add(last[a[j]], -1);
add(j, 1), last[a[j]] = j;
}
k[i].ans = getsum(k[i].r) - getsum(k[i].l - 1);
}
sort(k + 1, k + 1 + q, cmp2);
F(i, 1, q) printf("%d\n", k[i].ans);
return 0;
}
int read()
{
int x = 0;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}

【题解】P1972 [SDOI2009]HH的项链 - 树状数组的更多相关文章

  1. luogu P1972 [SDOI2009]HH的项链 |树状数组 或 莫队

    题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长. ...

  2. 洛谷 P1972 [SDOI2009]HH的项链——树状数组

    先上一波题目 https://www.luogu.org/problem/P1972 这道题是询问区间内不同数的个数 明显不是正常的数据结构能够维护的 首先考虑 因为对于若干个询问的区间[l,r],如 ...

  3. 【bzoj1878】[SDOI2009]HH的项链 树状数组

    题目描述 HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变得越来越长.有一 ...

  4. 【bzoj1878】[SDOI2009]HH的项链 - 树状数组 - 离线处理

    [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 4834  Solved: 2384[Submit][Status][Dis ...

  5. [BZOJ1878] [SDOI2009] HH的项链 (树状数组)

    Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变 ...

  6. bzoj 1878: [SDOI2009]HH的项链 ——树状数组+ 差分

    Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一 段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此他的项链变得 ...

  7. [SDOI2009]HH的项链 树状数组 BZOJ 1878

    题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链 ...

  8. 【P1972】HH的项链——树状数组+询问离线

    (题面摘自luogu) 题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集 ...

  9. BZOJ1878 [SDOI2009]HH的项链 树状数组 或 莫队

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1878 题意概括 给出一个长度为n的序列,用m次询问,问区间Li~Ri中有多少种不同的数. 0< ...

随机推荐

  1. 从JSON中自动生成对应的对象模型

    编程的乐趣和挑战之一,就是将体力活自动化,使效率成十倍百倍的增长. 需求 做一个项目,需要返回一个很大的 JSON 串,有很多很多很多字段,有好几层嵌套.前端同学给了一个 JSON 串,需要从这个 J ...

  2. Apple的Core ML3简介——为iPhone构建深度学习模型(附代码)

    概述 Apple的Core ML 3是一个为开发人员和程序员设计的工具,帮助程序员进入人工智能生态 你可以使用Core ML 3为iPhone构建机器学习和深度学习模型 在本文中,我们将为iPhone ...

  3. 常见Web安全漏洞--------sql注入

    SQL注入:利用现有应用程序,将(恶意)的SQL命令注入到后台数据库执行一些恶意的操作.在mybatis 中比较容易出现:${} 会发生sql 注入问题 #{}: 解析为一个 JDBC 预编译语句(p ...

  4. Spring Boot熟稔于心的20个常识

    1.什么是 Spring Boot? Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供 ...

  5. nginx 报 502 bad gateway 分析解决

    出现nginx 502 bad gateway 问题,先从nginx端日志入手,分析排查原因. 1.排查问题 首先需要打开nginx错误日志. 编辑nginx.conf,默认路径在/usr/local ...

  6. Java复合优先于继承

    复合优于继承 继承打破了封装性(子类依赖父类中特定功能的实现细节) 合理的使用继承的情况: 在包内使用 父类专门为继承为设计,并且有很好的文档说明,存在is-a关系 只有当子类真正是父类的子类型时,才 ...

  7. c#的全局异常捕获

    以下操作在Program.cs中 1.最简单的方式try...catch.. 一般用在某一段容易出错的代码,如果用在整个软件排查,如下所示 static void Main() { try { App ...

  8. 1272: 【基础】求P进制数的最大公因子与最小公倍数

    1272: [基础]求P进制数的最大公因子与最小公倍数 时间限制: 1 Sec 内存限制: 16 MB 提交: 684 解决: 415 [提交] [状态] [讨论版] [命题人:外部导入] 题目描述 ...

  9. 数据挖掘 决策树 Decision tree

    数据挖掘-决策树 Decision tree 目录 数据挖掘-决策树 Decision tree 1. 决策树概述 1.1 决策树介绍 1.1.1 决策树定义 1.1.2 本质 1.1.3 决策树的组 ...

  10. MySQL 数据备份与同步

    前段时间使用MySQL作为数据存储做了一个小项目.项目上线运行了几十天之后,数据已经越来越多,达到了100多M.用mysqldump每天备份全量数据然后传输到另外一台机器上这种方式进行数据备份,久而久 ...