【题解】bzoj-2653 Middle

Problem

bzoj&洛谷

题意:给定长为n的序列,共q次询问子序列 ( l , r ) , l [ a , b ] , r [ c , d ] 的中位数最大值,强制在线

Solution

对于一个序列,定有比中位数大的元素和比中位数小的元素一样多

转化成+1与-1,比中位数大的设为+1,小的设为-1,则只要有一段指定区间内的和为非负数,则该元素可以作为中位数存在

可是大小是相比较而言的,则可以根据每一个元素作为参考,建立出n棵线段树,这一步可以用主席树

每次二分中位数,查看该棵线段树下指定区间内的最大子段和是否为非负数,这里是线段树基础操作

Code

#include<algorithm>
#include<cstdio>
#include<cctype>
using namespace std;
typedef long long ll;
#define rg register
#define cl(x) memset(x,0,sizeof(x))

template <typename _Tp> inline _Tp read(_Tp&x){
    rg char c11=getchar(),ob=0;x=0;
    while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
    while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}

const int N=21000,L=1000000;
struct lst{int l,r,lx,rx,s;}seg[L];
int a[N],id[N],rt[N];
int n,m,tot;

inline int cmp(const int&cp1,const int&cp2){return a[cp1]<a[cp2];}

inline void up(int x){
    seg[x].s=seg[seg[x].l].s+seg[seg[x].r].s;
    seg[x].lx=max(seg[seg[x].l].lx,seg[seg[x].l].s+seg[seg[x].r].lx);
    seg[x].rx=max(seg[seg[x].r].rx,seg[seg[x].r].s+seg[seg[x].l].rx);
    return ;
}

inline void build(int&x,int l,int r){
    x=++tot;
    if(l==r){
        seg[x].lx=seg[x].rx=seg[x].s=1;
        return ;
    }
    int mid=(l+r)>>1;
    build(seg[x].l,l,mid);
    build(seg[x].r,mid+1,r);
    up(x);return ;
}

inline void update(int las,int&x,int l,int r,int pos){
    seg[x=++tot]=seg[las];
    if(l==r){
        seg[x].lx=seg[x].rx=seg[x].s=-1;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)update(seg[las].l,seg[x].l,l,mid,pos);
    else update(seg[las].r,seg[x].r,mid+1,r,pos);
    up(x);return ;
}

inline int qs(int x,int l,int r,int L,int R){
    if(L<=l&&r<=R)return seg[x].s;
    int mid=(l+r)>>1,res(0);
    if(L<=mid)res+=qs(seg[x].l,l,mid,L,R);
    if(mid<R)res+=qs(seg[x].r,mid+1,r,L,R);
    return res;
}

inline int ql(int x,int l,int r,int L,int R){
    if(l==L&&r==R)return seg[x].lx;
    int mid=(l+r)>>1;
    if(R<=mid)return ql(seg[x].l,l,mid,L,R);
    if(mid<L)return ql(seg[x].r,mid+1,r,L,R);
    return max(ql(seg[x].l,l,mid,L,mid),qs(seg[x].l,l,mid,L,mid)+ql(seg[x].r,mid+1,r,mid+1,R));
}

inline int qr(int x,int l,int r,int L,int R){
    if(l==L&&R==r)return seg[x].rx;
    int mid=(l+r)>>1;
    if(R<=mid)return qr(seg[x].l,l,mid,L,R);
    if(mid<L)return qr(seg[x].r,mid+1,r,L,R);
    return max(qr(seg[x].r,mid+1,r,mid+1,R),qs(seg[x].r,mid+1,r,mid+1,R)+qr(seg[x].l,l,mid,L,mid));
}

inline int check(int k,int*q){
    int res(0);
    if(q[2]+1<q[3])res+=qs(rt[k],1,n,q[2]+1,q[3]-1);
    res+=ql(rt[k],1,n,q[3],q[4]);
    res+=qr(rt[k],1,n,q[1],q[2]);
    return res>=0;
}

int main(){
    read(n);
    for(rg int i=1;i<=n;++i)read(a[i]),id[i]=i;
    sort(id+1,id+n+1,cmp);
    build(rt[1],1,n);
    for(rg int i=2;i<=n;++i)update(rt[i-1],rt[i],1,n,id[i-1]);
    read(m);
    int q[5],lastans(0);
    while(m--){
        for(rg int i=1;i<5;++i)read(q[i]),q[i]=((ll)q[i]+lastans)%n+1;
        sort(q+1,q+5);
        rg int l=1,r=n+1,mid;
        while(l+1<r){
            mid=(l+r)>>1;
            if(check(mid,q))l=mid;
            else r=mid;
        }
        printf("%d\n",lastans=a[id[l]]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40515553/article/details/80138260
今日推荐