题目大意:给一个区间,多次询问,每次问区间$[l,r]$里最近的两个相同的数的距离是多少。

题解:用一个数组$pre_i$表示第$i$个数前面最近的一个相同的数在哪,询问变成了询问$[l,r]$中$i-pre_i$的最小值,且$pre_i\in[l,r]$。难度就在处理$pre_i\not\in[l,r]$上。

$$
\because pre_i<i,i\in[l,r]\\
\therefore pre_i<r\\
若pre_i\not\in[l,r]\\
则pre_i<l
$$

这题没有修改,可以把询问按$l$排序,把不合法的点贡献去掉

卡点:$map$没更新

C++ Code:

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <map>
  4. #define maxn 500010
  5. const int inf = 0x3f3f3f3f;
  6. inline int min(int a, int b) {return a < b ? a : b;}
  7.  
  8. int a[maxn], pre[maxn], nxt[maxn];
  9. std::map<int, int> mp;
  10. struct Query {
  11. int l, r, id;
  12. inline bool operator < (const Query &rhs) const {return l < rhs.l;}
  13. } Q[maxn];
  14. int ans[maxn];
  15.  
  16. int V[maxn << 2];
  17. inline void update(int rt) {
  18. V[rt] = min(V[rt << 1], V[rt << 1 | 1]);
  19. }
  20. void build(int rt, int l, int r) {
  21. if (l == r) {
  22. if (pre[l]) V[rt] = l - pre[l];
  23. else V[rt] = inf;
  24. return ;
  25. }
  26. int mid = l + r >> 1;
  27. build(rt << 1, l, mid);
  28. build(rt << 1 | 1, mid + 1, r);
  29. update(rt);
  30. }
  31. void modify(int rt, int l, int r, int p) {
  32. if (l == r) {
  33. V[rt] = inf;
  34. return ;
  35. }
  36. int mid = l + r >> 1;
  37. if (p <= mid) modify(rt << 1, l, mid, p);
  38. else modify(rt << 1 | 1, mid + 1, r, p);
  39. update(rt);
  40. }
  41. int query(int rt, int l, int r, int L, int R) {
  42. if (L <= l && R >= r) return V[rt];
  43. int mid = l + r >> 1, ans = inf;
  44. if (L <= mid) ans = query(rt << 1, l, mid, L, R);
  45. if (R > mid) ans = min(ans, query(rt << 1 | 1, mid + 1, r, L, R));
  46. return ans;
  47. }
  48.  
  49. int n, m;
  50. int main() {
  51. scanf("%d%d", &n, &m);
  52. for (int i = 1; i <= n; i++) {
  53. scanf("%d", a + i);
  54. if (mp.count(a[i])) pre[i] = mp[a[i]], nxt[mp[a[i]]] = i, mp[a[i]] = i;
  55. else pre[i] = 0, mp[a[i]] = i;
  56. }
  57. for (int i = 1; i <= m; i++) {
  58. scanf("%d%d", &Q[i].l, &Q[i].r);
  59. Q[i].id = i;
  60. }
  61. std::sort(Q + 1, Q + m + 1);
  62. build(1, 1, n);
  63. int last = 1;
  64. for (int i = 1; i <= m; i++) {
  65. int l = Q[i].l;
  66. for (; last < l; last++) {
  67. if (nxt[last] >= l) modify(1, 1, n, nxt[last]);
  68. }
  69. ans[Q[i].id] = query(1, 1, n, l, Q[i].r);
  70. }
  71. for (int i = 1; i <= m; i++) if (ans[i] != inf) printf("%d\n", ans[i]);
  72. else puts("-1");
  73. return 0;
  74. }

  

[CF522D]Closest Equals的更多相关文章

  1. VK Cup 2015 - Qualification Round 1 D. Closest Equals 离线+线段树

    题目链接: http://codeforces.com/problemset/problem/522/D D. Closest Equals time limit per test3 secondsm ...

  2. Codeforces VK Cup 2015 - Qualification Round 1 D. Closest Equals 离线线段树 求区间相同数的最小距离

    D. Closest Equals Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/prob ...

  3. D. Closest Equals(线段树)

    题目链接: D. Closest Equals time limit per test 3 seconds memory limit per test 256 megabytes input stan ...

  4. Codeforces VK CUP 2015 D. Closest Equals(线段树+扫描线)

    题目链接:http://codeforces.com/contest/522/problem/D 题目大意:  给你一个长度为n的序列,然后有m次查询,每次查询输入一个区间[li,lj],对于每一个查 ...

  5. codeforces 522D. Closest Equals 线段树+离线

    题目链接 n个数m个询问, 每次询问输出给定区间中任意两个相同的数的最近距离. 先将询问读进来, 然后按r从小到大排序, 将n个数按顺序插入, 并用map统计之前是否出现过, 如果出现过, 就更新线段 ...

  6. Codeforces 522D Closest Equals

    题解: 傻逼题 直接从左向右扫描每个点作为右端点 然后单点修改区间查询就行了 另外一种更直观的做法就是$(i,j)$之间产生了$(j-i)$ 于是变成矩形查最大值,kd-tree维护 代码: #inc ...

  7. CodeForces 522D Closest Equals 树状数组

    题意: 给出一个序列\(A\),有若干询问. 每次询问某个区间中值相等且距离最短的两个数,输出该距离,没有则输出-1. 分析: 令\(pre_i = max\{j| A_j = A_i, j < ...

  8. $Codeforces\ 522D\ Closest\ Equals$ 线段树

    正解:线段树 解题报告: 传送门$QwQ$ 题目大意是说给定一个数列,然后有若干次询问,每次询问一个区间内相同数字之间距离最近是多少$QwQ$.如果不存在相同数字输出-1就成$QwQ$ 考虑先预处理出 ...

  9. CF数据结构练习

    1. CF 438D The Child and Sequence 大意: n元素序列, m个操作: 1,询问区间和. 2,区间对m取模. 3,单点修改 维护最大值, 取模时暴力对所有>m的数取 ...

随机推荐

  1. C#如何使用异步编程【BeginInvoke/EndInvoke】

    怎么使用异步,就是用委托进行处理,如果委托对象在调用列表中只有一个方法,它就可以异步执行这个方法.委托类有两个方法,叫做BeginInvoke和EndInvoke,它们是用来异步执行使用. 异步有三种 ...

  2. 如何在RedHat 7.0系统中安装mysql 5.7.22

    如何在RedHat 7.0系统中安装mysql 5.7.22 今天给大家介绍一下如何安装mysql5.7,在安装之前,首先要查看的是,你的系统中有没有已经安装过的情况.键入rpm -qa|grep m ...

  3. motto - question - bodyParser.urlencoded 中设置 extended 为 true 和 false 有什么区别吗?

    本文搜索关键字:motto node nodejs js javascript body-parser bodyparser urlencoded x-www-form-urlencoded exte ...

  4. JS - 给String.prototype添加replaceAll方法

    String.prototype.replaceAll = function (targetStr, newStr) {  var sourceStr = this.valueOf();  while ...

  5. matlab2018a安装后帮助文档打不开解决方法

    安装matlab2018a破解版后,帮助文档提示需要许可证问题(破解版没有可用许可证): 解决方法是把文档设置为离线即可(预设---->帮助---->安装在本地---->小窗口)

  6. DB设计工具——dbschema

      Preface       I've got a db design job about meeting room booking system last week.There're many s ...

  7. laravel 安装excel扩展

    1,使用Composer安装依赖 在Laravel项目根目录下使用Composer安装依赖: composer require maatwebsite/excel ~2.1 ps:一定要加上~2.1! ...

  8. 关于 cmd 控制台默认代码页编码的几种方法

    造成的中文及特殊字符乱码. 第一种:临时性修改编码 使用 chcp 命令,例如 chcp 65001 ,这回将当前代码页变为 utf-8编码,不过这种方式在关闭 cmd 之后会自动失效. 常用的编码及 ...

  9. C语言进阶—— 单引号和双引号14

    单引号和双引号 C语言中的单引号用来表示字符字面量 C语言中的双引号用来表示字符串字面量 ‘a’表示字符字面量,在内存中占用一个字节,'a'+1表示'a'的ASCII码加1,结果为'b' " ...

  10. Android面试收集录13 Android虚拟机及编译过程

    一.什么是Dalvik虚拟机 Dalvik是Google公司自己设计用于Android平台的Java虚拟机,它是Android平台的重要组成部分,支持dex格式(Dalvik Executable)的 ...