题目

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

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

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

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

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

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

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

#include<bits/stdc++.h>
using namespace std;
namespace IO
{
char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[20],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
void Put(char x){*oS++=x;if(oS==oT)Flush();}
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;}
void write(int x){int top=0;while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('\n');}
}
using namespace IO;
int max(int a,int b){return a>b? a:b;}
#define N 100007
#define mid ((l+r)>>1)
int root[N],q[4],id[N],a[N],ls[N<<4],rs[N<<4],cnt,n;
struct node{int lv,rv,sum;void init(){lv=rv=-N,sum=0;}}Ans,v[N<<4];
int cmp(int x,int y){return a[x]<a[y];}
node merge(node a,node b)
{
node c;
c.lv=max(a.lv,a.sum+b.lv);
c.rv=max(b.rv,b.sum+a.rv);
c.sum=a.sum+b.sum;
return c;
}
void build(int &p,int l,int r)
{
p=++cnt,v[p].lv=v[p].rv=v[p].sum=r-l+1;
if(l^r) build(ls[p],l,mid),build(rs[p],mid+1,r);
}
void modify(int &p,int l,int r,int x)
{
v[++cnt]=v[p],ls[cnt]=ls[p],rs[cnt]=rs[p],p=cnt;
if(l==r) return (void)(v[p].lv=v[p].rv=v[p].sum=-1);
(x<=mid? modify(ls[p],l,mid,x):modify(rs[p],mid+1,r,x)),v[p]=merge(v[ls[p]],v[rs[p]]);
}
void query(int p,int l,int r,int L,int R)
{
if(L<=l&&r<=R) return (void)(Ans=merge(Ans,v[p]));
if(L<=mid) query(ls[p],l,mid,L,R);
if(R>mid) query(rs[p],mid+1,r,L,R);
}
int check(int p)
{
int sum=0;
if(q[1]+1<=q[2]-1) Ans.init(),query(root[p],1,n,q[1]+1,q[2]-1),sum+=Ans.sum;
Ans.init(),query(root[p],1,n,q[0],q[1]),sum+=Ans.rv;
Ans.init(),query(root[p],1,n,q[2],q[3]),sum+=Ans.lv;
return sum>=0;
}
int main()
{
int i,Q,ans,l,r;
n=read(),build(root[1],1,n),v[0].init();
for(i=1;i<=n;++i) a[i]=read(),id[i]=i;
sort(id+1,id+n+1,cmp);
for(i=2;i<=n;++i) root[i]=root[i-1],modify(root[i],1,n,id[i-1]);
for(Q=read(),ans=0;Q;--Q)
{
for(i=0;i<4;++i) q[i]=(read()+ans)%n+1;
sort(q,q+4),l=1,r=n;
while(l<=r) check(mid)? (ans=a[id[mid]],l=mid+1):(r=mid-1);
write(ans);
}
return Flush(),0;
}

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. 51 nod 1127最短的包含字符串(尺取法)

    1127 最短的包含字符串   收藏  关注 给出一个字符串,求该字符串的一个子串S,S包含A-Z中的全部字母,并且S是所有符合条件的子串中最短的,输出S的长度.如果给出的字符串中并不包括A-Z中的全 ...

  2. 【LOJ2604】「NOIP2012」开车旅行

    [题目链接] [点击打开链接] [题目大意] 从西到东的坐标轴\([1,n]\)上有\(n\)个海拔互不相同的城市,每两个城市之间的距离定义为\(dis(i,j)=|h_i-h_j|\) 小\(A\) ...

  3. sh_06_元组基本使用

    sh_06_元组基本使用 info_tuple = ("zhangsan", 18, 1.75, "zhangsan") # 1. 取值和取索引 print(i ...

  4. max函数结合lambda使用

    说明:d.keys() 以及列表可以看做lambda函数的实参,max的判断对象是key的值.最终返回的是使得key的值最大的那个实参.

  5. pip安装源和虚拟环境的搭建

    一.pip安装源 1.介绍 采用国内源,加速下载模块的速度 常用pip源: 豆瓣:https://pypi.douban.com/simple 阿里:https://mirrors.aliyun.co ...

  6. 51Nod 1005 有负数的高精度加法

    51Nod是个好地方啊 题意 51Nod基础题第二题,高精度加法,可能有负数. 解题 如果按照一般的高精度,我们发现要分情况讨论,还要写高精度加法和减法,代码实现有点烦.而初中数学里说,省略加号的和. ...

  7. AcWing:138. 兔子与兔子(字符串Hash)

    很久很久以前,森林里住着一群兔子. 有一天,兔子们想要研究自己的 DNA 序列. 我们首先选取一个好长好长的 DNA 序列(小兔子是外星生物,DNA 序列可能包含 26 个小写英文字母). 然后我们每 ...

  8. C1:DOM 元素的尺寸和位置

    DOM元素的尺寸和位置 DOM 元素的尺寸 DOM.offsetWidth/offsetHeight: 包括内容区宽/高,padding,border,不包括margin.如果元素的box-sizei ...

  9. python 判断是字母的多种方法

    方法一:isalpha() "a".isalpha()   方法二:string.letters string.uppercase  import string  s=" ...

  10. 套接字之select系统调用

    select是IO多路复用的一种方式,用来等待一个列表中的多个描述符的可读可写状态: SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_ ...