题意:有A1 ~ An组成的数组,给你l r,L = min((l + ans[i - 1]) % n + 1, (r + ans[i - 1]) % n + 1),R = max((l + ans[i - 1]) % n + 1, (r + ans[i - 1]) % n + 1),你先需要的到L,R区间有k个不同的数字,然后问你L,R区间第(k + 1)/ 2个不同的数字下标是多少?

思路:显然是个在线询问。

我们之前已经会用主席树求区间内有多少不同数字了:从左到右把每个数字的位置存进每个操作的线段树,如果之前这个数已经出现,就在当前这棵线段树中删掉之前出现的位置,以保证每个数字出现的唯一性。显然每个区间保存的是某个数字最右边出现的位置。

但是这里显然我们不能去直接求第(k + 1)/ 2个不同的数字下标,因为我这里要求的是最早出现第(k + 1)/ 2个数的位置。那我直接从n往1建主席树,那我就变成了每个区间保存的是某个数字最左边出现的位置,显然我第i棵树并没有保存i前面的位置,那我就可以直接求i到后面任意位置的区间的第p个不相同数出现的位置。

代码:

  1. #include<cmath>
  2. #include<set>
  3. #include<map>
  4. #include<queue>
  5. #include<cstdio>
  6. #include<vector>
  7. #include<cstring>
  8. #include <iostream>
  9. #include<algorithm>
  10. using namespace std;
  11. typedef long long ll;
  12. typedef unsigned long long ull;
  13. const int maxn = 2e5 + ;
  14. const int M = maxn * ;
  15. const ull seed = ;
  16. const int INF = 0x3f3f3f3f;
  17. const int MOD = ;
  18. int a[maxn], root[maxn], tot;
  19. int n, q;
  20. struct node{
  21. int lson, rson;
  22. int sum;
  23. }T[maxn * ];
  24. int fa[maxn], ans[maxn];
  25. void init(){
  26. tot = ;
  27. memset(fa, -, sizeof(fa));
  28. memset(T, , sizeof(T));
  29. }
  30. void update(int l, int r, int &now, int pre, int pos, int v){
  31. T[++tot] = T[pre], now = tot;
  32. T[now].sum += v;
  33. if(l == r) return;
  34. int m = (l + r) >> ;
  35. if(pos <= m)
  36. update(l, m, T[now].lson, T[pre].lson, pos, v);
  37. else
  38. update(m + , r, T[now].rson, T[pre].rson, pos, v);
  39. }
  40. int query1(int l, int r, int L, int R, int now){
  41. if(L <= l && R >= r){
  42. return T[now].sum;
  43. }
  44. int m = (l + r) >> , sum = ;
  45. if(L <= m)
  46. sum += query1(l, m, L, R, T[now].lson);
  47. if(R > m)
  48. sum += query1(m + , r, L, R, T[now].rson);
  49. return sum;
  50. }
  51. int query2(int l, int r, int now, int k){
  52. if(l == r) return l;
  53. int m = (l + r) >> ;
  54. int sum = T[T[now].lson].sum;
  55. if(sum >= k)
  56. return query2(l, m, T[now].lson, k);
  57. else
  58. return query2(m + , r, T[now].rson, k - sum);
  59. }
  60. int main(){
  61. int ca = , t;
  62. scanf("%d" ,&t);
  63. while(t--){
  64. init();
  65. scanf("%d%d", &n, &q);
  66. root[n + ] = ;
  67. for(int i = ; i <= n; i++)
  68. scanf("%d", &a[i]);
  69. for(int i = n; i >= ; i--){
  70. if(fa[a[i]] == -){
  71. update(, n, root[i], root[i + ], i, );
  72. fa[a[i]] = i;
  73. }
  74. else{
  75. update(, n, root[i], root[i + ], i, );
  76. update(, n, root[i], root[i], fa[a[i]], -);
  77. fa[a[i]] = i;
  78. }
  79. }
  80. ans[] = ;
  81. for(int i = ; i <= q; i++){
  82. int l, r, L, R, k;
  83. scanf("%d%d", &l, &r);
  84. L = min((l + ans[i - ]) % n + , (r + ans[i - ]) % n + );
  85. R = max((l + ans[i - ]) % n + , (r + ans[i - ]) % n + );
  86. k = query1(, n, L, R, root[L]);
  87. ans[i] = query2(, n, root[L], (k + ) / );
  88. }
  89. printf("Case #%d:", ca++);
  90. for(int i = ; i <= q; i++)
  91. printf(" %d", ans[i]);
  92. printf("\n");
  93. }
  94.  
  95. return ;
  96. }

HDU 5919 Sequence II(主席树)题解的更多相关文章

  1. HDU 5919 Sequence II 主席树

    Sequence II Problem Description   Mr. Frog has an integer sequence of length n, which can be denoted ...

  2. HDU 5919 Sequence II(主席树+逆序思想)

    Sequence II Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) To ...

  3. HDU 5919 -- Sequence II (主席树)

    题意: 给一串数字,每个数字的位置是这个数第一次出现的位置. 每个询问对于序列的一个子区间,设一共有k个不同的数,求第ceil(k/2)个数的位置. 因为强制在线,所以离线乱搞pass掉. 主席树可解 ...

  4. HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)

    HDU 5919 题意: 动态处理一个序列的区间问题,对于一个给定序列,每次输入区间的左端点和右端点,输出这个区间中:每个数字第一次出现的位子留下, 输出这些位子中最中间的那个,就是(len+1)/2 ...

  5. hdu 5919 Sequence II (可持久化线段树)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5919 大致题意: 给你一个长度为n的序列,q个询问,每次询问是给你两个数x,y,经过与上一次的答案进行运算 ...

  6. HDU5919 Sequence II(主席树)

    Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,⋯,ana1,a2,⋯,anThere are ...

  7. HDU - 5919 Sequence II

    题意: 给定长度为n的序列和q次询问.每次询问给出一个区间(L,R),求出区间内每个数第一次出现位置的中位数,强制在线. 题解: 用主席树从右向左的插入点.对于当前点i,如果a[i]出现过,则把原位置 ...

  8. hdu 5147 Sequence II【树状数组/线段树】

    Sequence IITime Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem ...

  9. HDU 5919 Sequence II(主席树+区间不同数个数+区间第k小)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=5919 题意:给出一串序列,每次给出区间,求出该区间内不同数的个数k和第一个数出现的位置(将这些位置组 ...

随机推荐

  1. IDEA中创建maven项目后解决main文件夹下目录不全的问题

    IDEA创建maven-archetype-webapp项目的时候,创建完成后发现在main文件夹下没有java,resource等源文件夹. 解决方法: 1.选择File->Project S ...

  2. Copy & XCopy

    1):copy不能在有子目录存在的文件中拷贝文件的同时重命名此文件名(注:这里C:为根目录,bat为子目录),而xcopy能,不过会出现提示,当然你可以加参数而不使它提示. C:\>copy c ...

  3. react学习过程中遇到的错误记录

    1.App.js的代码如下: import React, { Component } from 'react'; import Test from './components/Test.jsx'; i ...

  4. opencart3图片Google Merchant Center验证通过不了的解决方法

    最近在做一个opencart项目,有对接Google Merchant Center,但是一直提示产品图片验证无法通过,ytkah看了一下图片路径,/image/cache/catalog/demo/ ...

  5. Python3学习之路~7.3 反射

    python中的反射功能是由以下四个内置函数提供:hasattr.getattr.setattr.delattr,该四个函数分别用于对对象内部执行:检查是否含有某成员.获取成员.设置成员.删除成员. ...

  6. Appium IOS 使用多模拟器并发执行测试

    申明一下   转载请注明出处  复制粘贴请滚蛋  !!!!!!!! 最近在是用appium进行app的并发测试,并且Android已经实现在同一台PC机使用多个模拟器并发测试的功能 这里说一句模拟器使 ...

  7. C# 字典Dictionary

    Dictionary<TKey, TValue> 泛型类提供了从一组键到一组值的映射.通过键来检索值的速度是非常快的,接近于 O(1),这是因为 Dictionary<TKey, T ...

  8. 【LeetCode每天一题】Set Matrix Zeroes(设置0矩阵)

    Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place. Exampl ...

  9. Jsoup解析XML

    先导入jsoup.jar  包 方法1:不推荐,了解即可 方法 方法3: 后期学习主流

  10. crypto++

    CryptoPP库是一个C++书写的加密算法库,很棒. 在如今的抛却数字证书体系下,只关注公私钥对的情况下,我认为存粹的加解密算法库很有市场,虽然我以前觉得PolarSSL的加解密算法实现不错,但不影 ...