AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2653

题目大意:多组询问,求左右端点在规定范围内移动所能得到的最大中位数。

[分析]

  求中位数这类题目比较少见[笔者见识少...],但是它的性质比较优美——从小到大排序排在中间的数字。

  如果往常求一个无序数列的中位数,最好的复杂度就是n*logn[快排一遍的复杂度],[因为你要知道每个元素在序列中的大小]

  但是我们这里是多组询问,而且元素不会修改,也就是每个元素的相对大小会在一开始预处理就搞定。

  现在我们再来想:左右端点只是一个范围,怎么求出满足情况的最优区间呢?

  根据时间的效率,肯定不能用枚举。

  那么这个区间就一定有性质,什么性质呢?中位数最大。

  我们要从中位数最大来找到这个区间。

  也就是这个区间里比中位数大的元素和比中位数小的元素一样多。

  可想而知:我们希望这个区间内的大的数越多,小的数越少越好,可是大小只是一个相对的概念,必须要和中位数比较才知道什么叫大,什么叫小。

  谁是最大的中位数呢?求的就是这个,我们怎么知道...那我们只好二分了。

  二分出这个中位数之后,我们要找这个最优区间就好办了:

  假设比中位数小的数值记作-1,比中位数大的数值记作1。

  最优区间一定满足:区间元素[指的是1,-1这些数]的和最大。

  求最大和的这个过程可以用很多数据结构解决了,即求[a,b]的右端最大+(b,c)的和+[c,d]的左端最大。

  可是我其实只需要这个值大于0,当前二分的值就是合法的了,我就会去追求一个更大的中位数,对吧。

  也就是说,思考的过程是:

    二分一个答案->找到最优的区间->区间如果满足->去追寻更好的答案。

  其中最优区间是找寻答案的前提,但只有先暂时确定一个较好值才能找到符合这个的最优区间。[逻辑上有点成环]

  

  最后因为对于每个二分出来的中位数值都希望有一个[-1,1]的序列专门分给它,这个靠什么呢?

  想起之前的可持久化线段树就好办了:

    树的节点意义是下标的位置范围,树的节点同时需要记录下这个节点代表区间的“右端最大”、“左端最大”、“求和”三种属性

    最小的元素所有位置都标上1[因为所有元素都比它大嘛...],

    然后从小到大的添加元素,先复制上一棵树,每次将树上上一个元素所在的位置标上-1,同时需要在过程中更新出右端最大、左端最大、求和三种属性。

    因为上一棵树和这一棵树的唯一区别就是上一棵树在上一个元素的位置上标记为1,而这一棵树标记为-1,这样每次就是更新树上的一条链,变化不会很大,采用的就是可持久化线段树的思想了。

  

最后献上代码:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4.  
  5. using namespace std;
  6.  
  7. inline int in(){
  8. int x=;char ch=getchar();
  9. while(ch>'' || ch<'') ch=getchar();
  10. while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
  11. return x;
  12. }
  13.  
  14. const int maxn=;
  15.  
  16. int n,m,key,cnt,ans;
  17. int a[maxn];
  18. int id[maxn],rt[maxn];
  19.  
  20. struct Node{
  21. int l,r,sz;
  22. int lx,rx,sm;
  23. }s[maxn*];
  24.  
  25. bool cmp(const int &x1,const int &x2){
  26. return a[x1]<a[x2];
  27. }
  28.  
  29. void renew(int x){
  30. s[x].sm=s[s[x].l].sm+s[s[x].r].sm;
  31. s[x].lx=max(s[s[x].l].lx,s[s[x].l].sm+s[s[x].r].lx);
  32. s[x].rx=max(s[s[x].r].rx,s[s[x].r].sm+s[s[x].l].rx);
  33. }
  34.  
  35. void build(int l,int r,int &rt){
  36. if(l==r){
  37. rt=++cnt,s[rt].sm=s[rt].lx=s[rt].rx=;
  38. return ;
  39. }
  40. rt=++cnt;
  41. int mid=(l+r)>>;
  42. build(l,mid,s[rt].l);
  43. build(mid+,r,s[rt].r);
  44. renew(rt);
  45. }
  46.  
  47. void update(int last,int l,int r,int &rt,int val){
  48. rt=++cnt;s[rt]=s[last];
  49. if(l==r){
  50. s[rt].lx=s[rt].rx=s[rt].sm=val;
  51. return ;
  52. }
  53. int mid=(l+r)>>;
  54. if(key<=mid) update(s[last].l,l,mid,s[rt].l,val);
  55. else update(s[last].r,mid+,r,s[rt].r,val);
  56. renew(rt);
  57. }
  58.  
  59. int get_all(int rt,int l,int r,int x,int y){
  60. if(l==x && r==y) return s[rt].sm;
  61. int mid=(l+r)>>;
  62. if(y<=mid)
  63. return get_all(s[rt].l,l,mid,x,y);
  64. else if(x>mid)
  65. return get_all(s[rt].r,mid+,r,x,y);
  66. else
  67. return get_all(s[rt].l,l,mid,x,mid)+get_all(s[rt].r,mid+,r,mid+,y);
  68. }
  69.  
  70. int get_lx(int rt,int l,int r,int x,int y){
  71. if(l==x && r==y) return s[rt].lx;
  72. int mid=(l+r)>>;
  73. if(y<=mid)
  74. return get_lx(s[rt].l,l,mid,x,y);
  75. else if(x>mid)
  76. return get_lx(s[rt].r,mid+,r,x,y);
  77. else
  78. return max(get_lx(s[rt].l,l,mid,x,mid),get_all(s[rt].l,l,mid,x,mid)+get_lx(s[rt].r,mid+,r,mid+,y));
  79. }
  80.  
  81. int get_rx(int rt,int l,int r,int x,int y){
  82. if(l==x && r==y) return s[rt].rx;
  83. int mid=(l+r)>>;
  84. if(y<=mid)
  85. return get_rx(s[rt].l,l,mid,x,y);
  86. else if(x>mid)
  87. return get_rx(s[rt].r,mid+,r,x,y);
  88. else
  89. return max(get_rx(s[rt].r,mid+,r,mid+,y),get_all(s[rt].r,mid+,r,mid+,y)+get_rx(s[rt].l,l,mid,x,mid));
  90. }
  91.  
  92. bool check(int k,int a,int b,int c,int d){
  93. int sum=;
  94. if(c>b+) sum+=get_all(rt[k],,n-,b+,c-);
  95. sum+=get_rx(rt[k],,n-,a,b);
  96. sum+=get_lx(rt[k],,n-,c,d);
  97. return sum>=;
  98. }
  99.  
  100. int main(){
  101. #ifndef ONLINE_JUDGE
  102. freopen("2653.in","r",stdin);
  103. freopen("2653.out","w",stdout);
  104. #endif
  105.  
  106. n=in();
  107. for(int i=;i<n;i++)
  108. a[i]=in(),id[i]=i;
  109. sort(id,id+n,cmp);
  110. build(,n-,rt[]);
  111. for(int i=;i<n;i++)
  112. key=id[i-],update(rt[i-],,n-,rt[i],-);
  113.  
  114. int ord[];
  115.  
  116. m=in();
  117. while(m--){
  118. ord[]=in(),ord[]=in(),ord[]=in(),ord[]=in();
  119. for(int i=;i<;i++)
  120. ord[i]=(ord[i]+ans)%n;
  121. sort(ord,ord+);
  122. int l=,r=n,mid;
  123. while(l+<r){
  124. mid=(l+r)>>;
  125. if(check(mid,ord[],ord[],ord[],ord[])) l=mid;
  126. else r=mid;
  127. }
  128. ans=a[id[l]];
  129. printf("%d\n",ans);
  130. }
  131.  
  132. return ;
  133. }

  

BZOJ 2653 middle的更多相关文章

  1. [BZOJ 2653] middle(可持久化线段树+二分答案)

    [BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...

  2. bzoj 2653: middle (主席树+二分)

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2522  Solved: 1434[Submit][Status][Disc ...

  3. BZOJ 2653: middle 主席树 二分

    https://www.lydsy.com/JudgeOnline/problem.php?id=2653 因为是两个方向向外延伸所以不能对编号取前缀和(这里只有前缀和向后传递的性质,不是实际意义的和 ...

  4. BZOJ 2653 middle | 主席树

    题目: http://www.lydsy.com/JudgeOnline/problem.php?id=2653 题解: 设答案为ans,把大于等于ans的记为1,小于的记为-1,这样可以知道当前an ...

  5. bzoj 2653 middle (可持久化线段树)

    middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1981  Solved: 1097[Submit][Status][Discuss] D ...

  6. BZOJ 2653: middle [主席树 中位数]

    传送门 题意: 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右 ...

  7. bzoj 2653 middle 二分答案 主席树判定

    判断中位数是否可行需要将当前的解作为分界,大于其的置为1,小于为-1,然后b-c必选,ab,cd可不选,这个用线段树判定就好 但不能每次跑,所以套主席树,按权值排序,构建主席树,更新时将上一个节点改为 ...

  8. BZOJ 2653 middle 二分答案+可持久化线段树

    题目大意:有一个序列,包含多次询问.询问区间左右端点在规定区间里移动所得到的最大中位数的值. 考虑对于每个询问,如何得到最优区间?枚举显然是超时的,只能考虑二分. 中位数的定义是在一个序列中,比中位数 ...

  9. bzoj 2653 middle(主席树)

    题面:https://vjudge.net/problem/HYSBZ-2653 博客:https://blog.csdn.net/litble/article/details/78984846 这个 ...

随机推荐

  1. qemu-kvm简单使用

    qemu-kvm主要有以下几个选项: -snapshot: 创建快照 -m: 指定内存大小 -smp: 指定处理器个数 -cpu: 指定CPU类型 -name: 设置虚拟机名称 -vnc: 使用vnc ...

  2. 自适应游标共享技术02(一个简单的例子来走近ACS)

    为了不让其他因素干扰实验,参数设置如下: optimizer_mode=ALL_ROWS(使用CBO) optimizer_features_enable=11.2.0.3(使用最新的优化参数) op ...

  3. 7.css盒模型

    所谓的盒模型,其实就是把元素当成盒子,元素里的文本就是盒子里的东西. 而根据元素的特效,其盒模型的特效也不同,下面是一些总结: 1.块级元素(区块) 所谓块级元素,就是能够设置元素尺寸.有隔离其他元素 ...

  4. python 小技巧(import模块、查询类继承关系、安装包)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在这里列举一些我使用Python时积累的小技巧.这些技巧是我在使用Python过程 ...

  5. Python学习教程(learning Python)--3.3 分支语句的条件表达式详解

    本节主要讨论分支语句的条件表达式问题. 在if或者if-else分支控制语句里由于都用到条件判断(表达式是真还是假),条件判断可以是一种关系运算也可以是布尔表达式. 本节将对if及if-else语句的 ...

  6. C基础 北京大公司面试简单总结

    作者有话说 这是关于程序员面试的一篇文章, 希望对你有帮助. 干了快3年了. 可以简单参考, 对比总结.虽然本人很水. 很喜欢当前做的手游项目.做的很认真.后端每个人技术都很好.但是结果都不如意.在死 ...

  7. zip压缩

    package com.green.project.compress; import java.io.File;import java.io.FileInputStream;import java.i ...

  8. 如何实现GridView的选中,编辑,取消,删除功能

    protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e) { string sqlstr = &qu ...

  9. zoj 2112 Dynamic Rankings

    原题链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1112 #include<cstdio> #include ...

  10. libevent简介 构成

    libevent简介 libevent是一个事件驱动的网络库,支持跨平台,如Linux, *BSD, MacOS X, Solaris, Windows.支持I/O多路复用,epoll.poll./d ...