[国家集训队]middle
作者:互联网
序列 \(a_{1...n}\) 的中位数定义为排好序后 \(a_{\lceil\frac n2\rceil}\)。给你 \(q\) 次询问(强制在线),询问 \(l\in [a,b],r\in[c,d]\) 的所有 \(a_{[l,r]}\) 的中位数最大值。n,q<=3e5
Hint
- 区间+中位数 ===========> 二分答案+把>=mid的设1,<mid的设-1
- 最大中位数:区间和最大,sum[b+1,c-1]+后缀最大值[a,b]+前缀最大值[c,d]
- 考虑check,先离散化a,预处理出每个mid=1...n的可供查询区间sum,maxsufsum,maxpresum的数据结构,由于每次只改动分界处的值对应的一些下标,总共改动O(n)次,所以用主席树。
#include <bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
inline int read(){
register char ch=getchar();register int x=0;
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x;
}
const int N=2e4+5;
int n,q,tot,a[N],arr[N],rt[N],x[4];
vector<int>b[N];
struct node {
int s,s1,s2,ls,rs;
}t[N<<5];
void pushup(int k){
t[k].s=t[t[k].ls].s+t[t[k].rs].s;
t[k].s1=max(t[t[k].ls].s1,t[t[k].ls].s+t[t[k].rs].s1);
t[k].s2=max(t[t[k].rs].s2,t[t[k].rs].s+t[t[k].ls].s2);
}
void build(int l,int r,int &k){
if(!k)k=++tot;
if(l==r){t[k].s=t[k].s1=t[k].s2=1;return;}
int mid=l+r>>1;
build(l,mid,t[k].ls),build(mid+1,r,t[k].rs);
pushup(k);
}
void chg(int p,int l,int r,int &k,int ok){
k=++tot,t[k]=t[ok];
if(l==r){t[k].s=t[k].s1=t[k].s2=-1;return;}
int mid=l+r>>1;
if(p<=mid)chg(p,l,mid,t[k].ls,t[ok].ls);
else chg(p,mid+1,r,t[k].rs,t[ok].rs);
pushup(k);
}
int ask(int L,int R,int l,int r,int k){
if(L<=l&&r<=R)return t[k].s;
int mid=l+r>>1,s=0;
if(L<=mid)s+=ask(L,R,l,mid,t[k].ls);
if(R>mid)s+=ask(L,R,mid+1,r,t[k].rs);
return s;
}
int ask1(int L,int R,int l,int r,int k){
if(L<=l&&r<=R)return t[k].s1;
int mid=l+r>>1,s=0;
if(L<=mid)s=ask1(L,R,l,mid,t[k].ls);
if(R>mid&&L>mid)s=ask1(L,R,mid+1,r,t[k].rs);
if(L<=mid&&R>mid)s=max(s,ask(L,R,l,mid,t[k].ls)+ask1(L,R,mid+1,r,t[k].rs));
// cout<<L<<' '<<R<<' '<<l<<' '<<r<<' '<<t[k].s<<' '<<s<<'\n';
return s;
}
int ask2(int L,int R,int l,int r,int k){
if(L<=l&&r<=R)return t[k].s2;
int mid=l+r>>1,s=0;
if(R>mid)s=ask2(L,R,mid+1,r,t[k].rs);
if(R<=mid&&L<=mid)s=ask2(L,R,l,mid,t[k].ls);
if(L<=mid&&R>mid)s=max(s,ask(L,R,mid+1,r,t[k].rs)+ask2(L,R,l,mid,t[k].ls));
return s;
}
int main(){
n=read();
for(int i=1;i<=n;i++)a[i]=read(),arr[i]=a[i];
sort(arr+1,arr+n+1);
int u=unique(arr+1,arr+n+1)-arr-1;
unordered_map<int,int>mp;
for(int i=1;i<=u;i++)mp[arr[i]]=i;
for(int i=1;i<=n;i++)a[i]=mp[a[i]],b[a[i]].push_back(i);
rt[1]=++tot;
build(1,n,rt[1]);
for(int i=2;i<=u;i++){
rt[i]=++tot;int las=rt[i-1];
for(int j:b[i-1])chg(j,1,n,rt[i],las),las=rt[i];
// puts("o");cout<<ask1(2,4,1,n,rt[i])<<' ';puts("oo");
}
q=read();
for(int o=0;q--;){
for(int i=0;i<4;i++)x[i]=(read()+o)%n+1;
sort(x,x+4);
int L=0,R=u+1,mid;
while(L<R-1){
mid=L+R>>1;//cout<<mid<<":\n";
if(ask1(x[2],x[3],1,n,rt[mid])+ask2(x[0],x[1],1,n,rt[mid])+(x[2]-x[1]<=1?0:ask(x[1]+1,x[2]-1,1,n,rt[mid]))>=0)L=mid;
else R=mid;
}
cout<<arr[L]<<'\n',o=arr[L];
}
}
标签:ch,rs,int,mid,中位数,middle,ls,国家集训队 来源: https://www.cnblogs.com/impyl/p/16343455.html