http://acm.split.hdu.edu.cn/showproblem.php?pid=5919

题意:
给出一串序列,每次给出区间,求出该区间内不同数的个数k和第一个数出现的位置(将这些位置组成一个新的序列),输出这里面的第ceil(k/2)个数。

思路:

因为每个区间只需要统计第一个数出现的位置,那么从右往左来建树,如果该数没有出现,那么就将该位置+1,否则要将上一次出现的位置-1后再在该位置+1。

统计不同数的个数很简单,就是线段树查询。

查询出第k小的数也很简单,因为我们是从后往前建树的,那么t[l]这棵树里面的元素就是从l开始的数组,直接线段树查询第k个数即可。

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<vector>
  6. #include<stack>
  7. #include<queue>
  8. #include<cmath>
  9. #include<map>
  10. #include<set>
  11. using namespace std;
  12. typedef long long ll;
  13. typedef pair<int,int> pll;
  14. const int INF = 0x3f3f3f3f;
  15. const int maxn = *1e5+;
  16.  
  17. int tot,n,m;
  18. int a[maxn],pre[maxn],rot[maxn];
  19.  
  20. struct node
  21. {
  22. int l,r,num;
  23. }t[maxn*];
  24.  
  25. int build(int l, int r)
  26. {
  27. int root=++tot;
  28. t[root].num=;
  29. if(l==r) return root;
  30. int mid=(l+r)>>;
  31. t[root].l=build(l,mid);
  32. t[root].r=build(mid+,r);
  33. return root;
  34. }
  35.  
  36. int update(int root, int pos, int d)
  37. {
  38. int now = ++tot;
  39. int tmp = now;
  40. t[tot].num = t[root].num + d;
  41. int l = , r = n;
  42. while(l<r)
  43. {
  44. int mid = (l+r)>>;
  45. if(pos<=mid)
  46. {
  47. t[now].l = ++tot;
  48. t[now].r = t[root].r;
  49. root = t[root].l;
  50. now = tot;
  51. r = mid;
  52. }
  53. else
  54. {
  55. t[now].l = t[root].l;
  56. t[now].r = ++tot;
  57. root = t[root].r;
  58. now = tot;
  59. l = mid + ;
  60. }
  61. t[now].num = t[root].num + d;
  62. }
  63. return tmp;
  64. }
  65.  
  66. int query(int ql ,int qr, int l, int r, int root)
  67. {
  68. if(ql<=l && qr>=r) return t[root].num;
  69. int mid = (l+r)>>;
  70. int ans = ;
  71. if(ql<=mid) ans+=query(ql,qr,l,mid,t[root].l);
  72. if(qr>mid) ans+=query(ql,qr,mid+,r,t[root].r);
  73. return ans;
  74. }
  75.  
  76. int calc(int l,int r,int k,int root)
  77. {
  78. if(l==r) return l;
  79. int mid = (l+r)>>;
  80. if(t[t[root].l].num>=k) return calc(l,mid,k,t[root].l);
  81. else return calc(mid+,r,k-t[t[root].l].num,t[root].r);
  82. }
  83.  
  84. int main()
  85. {
  86. //freopen("in.txt","r",stdin);
  87. int T;
  88. int kase = ;
  89. scanf("%d",&T);
  90. while(T--)
  91. {
  92. tot=;
  93. int bef=;
  94. memset(pre,-,sizeof(pre));
  95. scanf("%d%d",&n,&m);
  96. for(int i=;i<=n;i++) scanf("%d",&a[i]);
  97. rot[n+] = build(,n);
  98. for(int i=n;i>;i--)
  99. {
  100. if(pre[a[i]] == -) rot[i] = update(rot[i+],i,);
  101. else
  102. {
  103. int tmp = update(rot[i+],pre[a[i]],-);
  104. rot[i] = update(tmp,i,);
  105. }
  106. pre[a[i]] = i ;
  107. }
  108. printf("Case #%d:",++kase);
  109. while(m--)
  110. {
  111. int l,r;
  112. scanf("%d%d",&l,&r);
  113. int ll = (l + bef)%n + ;
  114. int rr = (r + bef)%n + ;
  115. l = min(ll, rr);
  116. r = max(ll, rr);
  117. int k = query(l,r,,n,rot[l]);
  118. k = ceil(k/2.0);
  119. int ans = calc(,n,k,rot[l]);
  120. bef = ans;
  121. printf(" %d",ans);
  122. }
  123. puts("");
  124. }
  125. return ;
  126. }

HDU 5919 Sequence II(主席树+区间不同数个数+区间第k小)的更多相关文章

  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 (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)

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

  3. hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)

    题目链接 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2 ...

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

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

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

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

  6. HDU 5919 Sequence II(主席树)题解

    题意:有A1 ~ An组成的数组,给你l r,L = min((l + ans[i - 1]) % n + 1, (r + ans[i - 1]) % n + 1),R = max((l + ans[ ...

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

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

  8. HDU5919 Sequence II(主席树)

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

  9. HDU - 5919 Sequence II

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

随机推荐

  1. HashMap 和 ConcurrentHashMap比较

    基础知识: 1. ConcurrentHashMap: (JDK1.7) segment数组,分段锁:segment 内部是 HashEnty数组,类似HashMap: 统计长度的方法,先不加锁统计两 ...

  2. 小米note3的开发者选项在哪里?怎么进入开发者模式?如何显示布局边界?

    小米note3的开发者选项在哪里?小米note3怎么进入开发者模式1.找到[设置],打开2.点击[我的设备]3.点击[全部参数]4.连续点击[MIUI版本]5次5.之后就会看见提示 “进入到开发者模式 ...

  3. linux内核的双链表list_head、散列表hlist_head

    一.双链表list_head 1.基本概念 linux内核提供的标准链表可用于将任何类型的数据结构彼此链接起来. 不是数据内嵌到链表中,而是把链表内嵌到数据对象中. 即:加入链表的数据结构必须包含一个 ...

  4. [C#基础]说说lock到底锁谁?(补充与修改)

    摘要 今天在园子里面有园友反馈关于[C#基础]说说lock到底锁谁?文章中lock(this)的问题.后来针对文章中的例子,仔细想了一下,确实不准确,才有了这篇文章的补充,已经对文章中的demo进行修 ...

  5. STM32硬件IIC (转)

    源: STM32硬件IIC

  6. javascript 与 PHP 通信加密,使用AES 128 CBC no padding,以及ios,java,c#文章例子

    运行环境 php7.0 不适用于 php7.0以上版本,因为mcrypt_encrypt()函数已删除 为何要采用 no padding 这种形式: AES加密如果原输入数据不够16字节的整数位,就要 ...

  7. The Architecture of Open Source Applications: Berkeley DB

    最近研究内存关系数据库的设计与实现,下面一篇为berkeley db原始两位作为的Berkeley DB设计回忆录: Conway's Law states that a design reflect ...

  8. mycat下mysql jdbc connector使用高版本报PacketTooBigException异常

    如下所示: 5.1.30切换为mysql-connector 5.1.46/40,报错,可参考https://blog.csdn.net/n447194252/article/details/7530 ...

  9. CentOS7 彻底关闭 IPV6

    查看服务监听的IP中是否有IPv6格式的地址 netstat -tuln 如果有tcp6协议的就是有打开ip6 编辑/etc/default/grub,在GRUB_CMDLINE_LINUX加上的后面 ...

  10. 20155201 李卓雯 《网络对抗技术》实验一 逆向及Bof基础

    20155201 李卓雯 <网络对抗技术>实验一 逆向及Bof基础 一.实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,f ...