题目

首先我们考虑解决中位数一类问题的常用手段:二分\(mid\),将大于等于它的设为\(1\),小于它的设为\(−1\),判断区间和是否\(\ge0\)。

对于询问\(a,b,c,d\),二分完\(mid\)后,我们需要判断\([a,b]\)的最大后缀和\(+[c,d]\)的最大前缀和\(+(b,c)\)的和是否\(\ge0\)。

因为中位数一定是序列中出现过的数,所以我们可以排序后二分第\(mid\)大。

考虑使用主席树维护区间和区间最大后缀和区间最大前缀和。

最开始先把所有数设为\(1\)建树。

然后每次从小到大把序列中的一个树改为\(-1\)建一个新版本。

查询的时候按上面的来就可以了。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. namespace IO
  4. {
  5. char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[20],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
  6. char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
  7. void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
  8. void Put(char x){*oS++=x;if(oS==oT)Flush();}
  9. int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
  10. void write(int x){int top=0;while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('\n');}
  11. }
  12. using namespace IO;
  13. int max(int a,int b){return a>b? a:b;}
  14. #define N 100007
  15. #define mid ((l+r)>>1)
  16. int root[N],q[4],id[N],a[N],ls[N<<4],rs[N<<4],cnt,n;
  17. struct node{int lv,rv,sum;void init(){lv=rv=-N,sum=0;}}Ans,v[N<<4];
  18. int cmp(int x,int y){return a[x]<a[y];}
  19. node merge(node a,node b)
  20. {
  21. node c;
  22. c.lv=max(a.lv,a.sum+b.lv);
  23. c.rv=max(b.rv,b.sum+a.rv);
  24. c.sum=a.sum+b.sum;
  25. return c;
  26. }
  27. void build(int &p,int l,int r)
  28. {
  29. p=++cnt,v[p].lv=v[p].rv=v[p].sum=r-l+1;
  30. if(l^r) build(ls[p],l,mid),build(rs[p],mid+1,r);
  31. }
  32. void modify(int &p,int l,int r,int x)
  33. {
  34. v[++cnt]=v[p],ls[cnt]=ls[p],rs[cnt]=rs[p],p=cnt;
  35. if(l==r) return (void)(v[p].lv=v[p].rv=v[p].sum=-1);
  36. (x<=mid? modify(ls[p],l,mid,x):modify(rs[p],mid+1,r,x)),v[p]=merge(v[ls[p]],v[rs[p]]);
  37. }
  38. void query(int p,int l,int r,int L,int R)
  39. {
  40. if(L<=l&&r<=R) return (void)(Ans=merge(Ans,v[p]));
  41. if(L<=mid) query(ls[p],l,mid,L,R);
  42. if(R>mid) query(rs[p],mid+1,r,L,R);
  43. }
  44. int check(int p)
  45. {
  46. int sum=0;
  47. if(q[1]+1<=q[2]-1) Ans.init(),query(root[p],1,n,q[1]+1,q[2]-1),sum+=Ans.sum;
  48. Ans.init(),query(root[p],1,n,q[0],q[1]),sum+=Ans.rv;
  49. Ans.init(),query(root[p],1,n,q[2],q[3]),sum+=Ans.lv;
  50. return sum>=0;
  51. }
  52. int main()
  53. {
  54. int i,Q,ans,l,r;
  55. n=read(),build(root[1],1,n),v[0].init();
  56. for(i=1;i<=n;++i) a[i]=read(),id[i]=i;
  57. sort(id+1,id+n+1,cmp);
  58. for(i=2;i<=n;++i) root[i]=root[i-1],modify(root[i],1,n,id[i-1]);
  59. for(Q=read(),ans=0;Q;--Q)
  60. {
  61. for(i=0;i<4;++i) q[i]=(read()+ans)%n+1;
  62. sort(q,q+4),l=1,r=n;
  63. while(l<=r) check(mid)? (ans=a[id[mid]],l=mid+1):(r=mid-1);
  64. write(ans);
  65. }
  66. return Flush(),0;
  67. }

Luogu P2839 [国家集训队]middle的更多相关文章

  1. P2839 [国家集训队]middle

    P2839 [国家集训队]middle 好妙的题啊,,,, 首先二分一个答案k,把数列里>=k的数置为1,=0就是k>=中位数,<0就是k<中位数 数列的最大和很好求哇 左边的 ...

  2. [洛谷P2839][国家集训队]middle

    题目大意:给你一个长度为$n$的序列$s$.$Q$个询问,问在$s$中的左端点在$[a,b]$之间,右端点在$[c,d]$之间的子段中,最大的中位数. 强制在线. 题解:区间中位数?二分答案,如果询问 ...

  3. Luogu 2839 [国家集训队]middle

    感觉这题挺好的. 首先对于中位数最大有一个很经典的处理方法就是二分,每次二分一个数组中的下标$mid$,然后我们把$mid$代回到原来的数组中检查,如果一个数$a_{i} \geq mid$,那么就把 ...

  4. 洛谷P2839 [国家集训队]middle 主席树_二分

    Code: #include <cstdio> #include <algorithm> #include <cstring> #include <strin ...

  5. [国家集训队]middle 解题报告

    [国家集训队]middle 主席树的想法感觉挺妙的,但是这题数据范围这么小,直接分块草过去不就好了吗 二分是要二分的,把\(<x\)置\(-1\),\(\ge x\)的置\(1\),于是我们需要 ...

  6. [国家集训队]middle

    [国家集训队]middle 题目 解法 开\(n\)颗线段树,将第\(i\)颗线段树中大于等于第\(i\)小的数权值赋为1,其他的则为-1,对于每个区间维护一个区间和,最大前缀和,最大后缀和. 然后二 ...

  7. luogu P2757 [国家集训队]等差子序列

    题目链接 luogu P2757 [国家集训队]等差子序列 题解 线段树好题 我选择暴力 代码 // luogu-judger-enable-o2 #include<cstdio> inl ...

  8. luogu P2619 [国家集训队2]Tree I

    题目链接 luogu P2619 [国家集训队2]Tree I 题解 普通思路就不说了二分增量,生成树check 说一下坑点 二分时,若黑白边权有相同,因为权值相同优先选白边,若在最有增量时出现黑白等 ...

  9. CF484E Sign on Fence && [国家集训队]middle

    CF484E Sign on Fence #include<bits/stdc++.h> #define RG register #define IL inline #define _ 1 ...

随机推荐

  1. EasyUI DataGrid列表,显示undefined

    datagrid中,显示undefined的解决方法 在get函数中,将为null的值返回空的字符串 1 public class TestModel { 2 3 private String key ...

  2. [模板] KMP算法/Border

    KMP 算法 KMP (Knuth-Morris-Pratt) 算法是一种在线性时间内匹配文本串和模式串的算法. 称字符串的 Border 集合为 \[ \operatorname {Border} ...

  3. JavaWeb_(SSH论坛)_五、帖子模块

    基于SSH框架的小型论坛项目 一.项目入门 传送门 二.框架整合 传送门 三.用户模块 传送门 四.页面显示 传送门 五.帖子模块 传送门 六.点赞模块 传送门 七.辅助模块 传送门 回复帖子 分析回 ...

  4. JS框架_(JQuery.js)上传进度条

    百度云盘 传送门 密码: 1pou 纯CSS上传进度条效果: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN ...

  5. scala基础-1

    函数式编程 ​ 并行编程 ​ 多核计算.云计算 ​ 引用透明,给值确定,结果也确定 数据类型 三种变量修饰符 ​ val 定义immutable variable ​ var 定义mutable va ...

  6. Java并发编程的艺术笔记(六)——HashMap、ConcurentHashMap的原理与实现

    一.线程不安全的HashMap 多线程环境下,使用HashMap进行put操作会引起死循环(jdk1.7 Entry链表形成环形数据结构),导致CPU利用率接近100%. 结构:数组 table[]+ ...

  7. shiro的web.xml的配置

    <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class&g ...

  8. 使用DBLink方式同步远程数据库中含Blob、Clob字段表的问题解决

    在数据库同步中我们经常会用到DBLink方式.DBLink可以将物理上存放于网络的多个数据库在逻辑上当成一个单一的大数据库.开发人员无需关心数据库的网络分布,就能很方便的实现从不同数据库之间读取数据. ...

  9. navicat常用快捷键与SQL基本使用

    一.Navicat常用快捷键 1,Ctrl+q就会弹出一个sql输入窗口 2,Ctrl+r就执行sql了 3,按f6会弹出一个命令窗口 4,Ctrl+/ 注释 5,Ctrl +Shift+/ 解除注释 ...

  10. Selenium-WebDriverApi接口

    webdriver获取元素的18种方式: 1.单数模式8 种 id定位模式 element = driver.find_element_by_id('i1') element.send_keys('U ...