(题面摘自luogu)

题目背景

题目描述

HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,因此,他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。

输入输出格式

输入格式:

第一行:一个整数N,表示项链的长度。

第二行:N 个整数,表示依次表示项链中贝壳的编号(编号为0 到1000000 之间的整数)。

第三行:一个整数M,表示HH 询问的个数。

接下来M 行:每行两个整数,L 和R(1 ≤ L ≤ R ≤ N),表示询问的区间。

输出格式:

M 行,每行一个整数,依次表示询问对应的答案。

说明

数据范围:

对于100%的数据,N <= 500000,M <= 500000。

  老师讲了两种办法,先只打了第一种。(好像莫队也能做……以后再说)

  首先我们把询问离线,按右端点排序。然后我们从左至右扫描原序列(可以离散化):假如我们想处理[l, r]这个询问,我们在扫描序列的时候把每个颜色对应的位置在树状数组中+1,扫描到r的时候直接查询[l, r]的区间和即可。但是布星,有重复的颜色怎么破?

  再来考虑我们扫描的过程:一个颜色产生对[l, r]的贡献,当且仅当这个颜色在已扫描序列[1, r]的最右端的位置pos,满足pos >= l。那么我们动态维护某个颜色出现的位置,在扫描的时候一边往BIT里扔贡献,一边删掉该颜色上次出现位置的贡献,然后更新这个颜色的最后一个位置。这时每查到一个询问再询问l, r区间和就是可行的。

  代码中有个小细节很坑,可供参考。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. //#define L second
  6. //#define R first
  7. //#define mp make_pair
  8. #define BUG puts("$$$")
  9. #define lowbit(i) (i & -i)
  10. #define maxn 500010
  11. template <typename T>
  12. void read(T &x) {
  13. x = 0;
  14. int f = 1;
  15. char ch = getchar();
  16. while (!isdigit(ch)) {
  17. if (ch == '-')
  18. f = -1;
  19. ch = getchar();
  20. }
  21. while (isdigit(ch)) {
  22. x = x * 10 + (ch ^ 48);
  23. ch = getchar();
  24. }
  25. x *= f;
  26. return;
  27. }
  28. using namespace std;
  29. struct Query {
  30. int l, r, id;
  31. friend bool operator < (Query a, Query b) {
  32. return a.r < b.r;
  33. }
  34. } Q[maxn];
  35. int bit[maxn], a[maxn], pos[maxn], n, m, N;
  36. int st[maxn], ans[maxn];//辅助
  37. int contra(int* a) {
  38. memcpy(st, a, sizeof(st));
  39. sort(st + 1, st + 1 + n);
  40. int len = unique(st + 1, st + 1 + n) - st - 1;
  41. for (int i = 1; i <= n; ++i)
  42. a[i] = lower_bound(st + 1, st + len + 1, a[i]) - st;
  43. return len;
  44. }
  45. void modify(int x, int del) {
  46. for (int i = x; i <= n; i += lowbit(i))
  47. bit[i] += del;
  48. }
  49. int query(int l, int r) {
  50. int sum = 0;
  51. for (int i = r; i; i -= lowbit(i))
  52. sum += bit[i];
  53. for (int i = l - 1; i; i -= lowbit(i))
  54. sum -= bit[i];
  55. return sum;
  56. }
  57. void solve() {
  58. register int i = 1, j = 1;//i指向序列,j指向询问
  59. while (j <= m) {
  60. while (i <= Q[j].r) {
  61. if (pos[a[i]])
  62. modify(pos[a[i]], -1);
  63. modify(i, 1);
  64. pos[a[i]] = i;
  65. ++i;
  66. }
  67. --i;  //这里:有可能出现右端点相同的情况,不加这句话就跳过了
  68. ans[Q[j].id] = query(Q[j].l, Q[j].r);
  69. ++j;
  70. }
  71. return;
  72. }
  73. int main() {
  74. read(n);
  75. for (int i = 1; i <= n; ++i)
  76. read(a[i]);
  77. contra(a);
  78. read(m);
  79. for (int i = 1; i <= m; ++i)
  80. read(Q[i].l), read(Q[i].r), Q[i].id = i;
  81. sort(Q + 1, Q + 1 + m);
  82. solve();
  83. for (int i = 1; i <= m; ++i)
  84. printf("%d\n", ans[i]);
  85. return 0;
  86. }

  另一种方法不用离线,我们用数组last记录每个位置上该颜色上次出现的位置(第一次出现记0),然后询问每个区间内,有多少个点i满足last[i] < l;但是这个东西怎么维护呢?我想想……我晓得了,是主席树!\(OwO)/ 以后再打吧。

【P1972】HH的项链——树状数组+询问离线的更多相关文章

  1. 【题解】P1972 [SDOI2009]HH的项链 - 树状数组

    P1972 [SDOI2009]HH的项链 声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 题目描述 \(HH\) 有一串由各种 ...

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

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

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

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

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

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

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

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

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

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

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

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

  8. BZOJ1878: [SDOI2009]HH的项链[树状数组 离线]

    1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3486  Solved: 1738[Submit][Statu ...

  9. luogu1972 HH的项链(树状数组)

    无修改.询问区间种类数的问题可以很容易地用树状数组解决 我们先给询问按右端点排序,然后推着做,每次让a[i]++,表示i处新增了一个种类 但是这样会和前面的有重复,我们只要记下每个种类上次在哪里出现过 ...

随机推荐

  1. zookeeper在Dubbo中角色与作用

    作者:倪炜链接:http://www.zhihu.com/question/25070185/answer/86166486来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处 ...

  2. 【DeepLearning】GoogLeNet

    InceptionV1 论文原文:Going deeper with convolutions    中英文对照 InceptionBN 论文原文:Batch Normalization: Accel ...

  3. 给 Mac 添加右键菜单「使用 VSCode 打开」

    最终的实现效果是在文件 / 文件夹上右击时,会出现菜单项「用 VSCode 打开」,点击后会启动 Visual Studio Code 打开对应的文件 / 文件夹. 实现步骤 打开「自动操作.app」 ...

  4. Alibaba Spring Cloud 微服务介绍(一)

    " Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案.此项目包含开发分布式应用服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件 ...

  5. Luogu P5450 [THUPC2018]淘米神的树

    题意 写的很明白了,不需要解释. \(\texttt{Data Range:}1\leq n\leq 234567\) 题解 国 际 计 数 水 平 首先考虑一开始只有一个黑点的情况怎么做. 我们钦定 ...

  6. 4G DTU是什么 可以应用于哪些行业?

    4G是什么? 4G是移动电话网络通过蜂窝塔传输的信号的名称,蜂窝塔连接到更宽的互联网.这些是当今智能手机使用的信号,当您外出时,可以通过手机上网,因此他们不依赖电缆或光纤,也就是说无线网. 使用合适的 ...

  7. 基于PHP实现短信验证码接口的方法

    步骤: 1.登录荣联运通讯注册获取ACCOUNT SID.AUTH TOKEN.Rest URL(生产).AppID(默认): 2.注册测试用手机号码(先注册测试号码方可使用): 3.下载demo示例 ...

  8. c100k

    sysctl -w fs.file-max=10485760 #系统允许的文件描述符数量10msysctl -w net.ipv4.tcp_rmem=1024 #每个tcp连接的读取缓冲区1k,一个连 ...

  9. 详解Git

    版本控制 基本概念 版本控制是一个非常简单的概念,我举个例子简单说明一下你就能大概明白它是一个什么东西,当你不会版本控制的时候: 你的BOSS决定做一款灰常牛逼的软件,找你进行开发 当你做好之后,老板 ...

  10. 用微信小程序做一个小电商 sku

    效果展示图 功能点概述 图一功能点有 搜索 轮播图 商品展示 图二功能点 导航栏 加入购物车 图四功能点 评论点 图五购物车 复选框 ( 全选全不选 ) 即点即改 总计结算 功能详解 1.A(搜索) ...