[国家集训队]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,
- 最大中位数:区间和最大,sum[b+1,c-1]+后缀最大值[a,b]+前缀最大值[c,d]
- 考虑check,先离散化a,预处理出每个mid=1...n的可供查询区间sum,maxsufsum,maxpresum的数据结构,由于每次只改动分界处的值对应的一些下标,总共改动O(n)次,所以用主席树。
#include
#define pii pair
#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];
vectorb[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<>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_mapmp;
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<>1;//cout<=0)L=mid;
else R=mid;
}
cout<