码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 2653: middle

时间:2018-02-06 13:05:37      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:body   post   i++   scanf   names   node   inline   std   else   

Description

一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。给你一个
长度为n的序列s。回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
其中a<b<c<d。位置也从0开始标号。我会使用一些方式强制你在线。

Solution

中位数的题一般是二分答案
二分一个中位数\(x\),如果是中位数则比它小的数和比它大的数绝对值不超过1
所以把大于\(x\)的数赋成1,小于\(x\)的数赋成-1,如果存在一个区间\([l,r]\)使得区间和等于0就可以满足条件
二分答案之后,要使得区间和尽量大
所以维护一个\([a,b]\)的最大后缀和,\([c,d]\)的最大前缀和,再加上\([b+1,c-1]\)的和就是最大区间的和
所以我们只需要对每一个权值维护一个线段树就行了, 维护方法和区间子段和类似

#include <bits/stdc++.h>
using namespace std;
const int N=20005;
int n,a[N],rt[N],b[N],num,Q,ans=0,q[5],cnt=0,id[N];
struct node{
    int ls,rs;
    int lsum,rsum,sum;
}tr[N*30];
inline void upd(int x){
    int ls=tr[x].ls,rs=tr[x].rs;
    tr[x].sum=tr[ls].sum+tr[rs].sum;
    tr[x].lsum=max(tr[ls].lsum,tr[ls].sum+tr[rs].lsum);
    tr[x].rsum=max(tr[rs].rsum,tr[rs].sum+tr[ls].rsum);
}
inline void build(int &x,int l,int r){
    x=++cnt;
    if(l==r){tr[x].lsum=tr[x].rsum=tr[x].sum=-1;return ;}
    int mid=(l+r)>>1;
    build(tr[x].ls,l,mid);build(tr[x].rs,mid+1,r);
    upd(x);
}
inline void ins(int &x,int l,int r,int sa){
    tr[++cnt]=tr[x];x=cnt;
    if(l==r){tr[x].lsum=tr[x].rsum=tr[x].sum=1;return ;}
    int mid=(l+r)>>1;
    if(sa<=mid)ins(tr[x].ls,l,mid,sa);
    else ins(tr[x].rs,mid+1,r,sa);
    upd(x);
}
inline node qry(int x,int l,int r,int sa,int se){
    if(sa<=l && r<=se)return tr[x];
    int mid=(l+r)>>1;
    if(se<=mid)return qry(tr[x].ls,l,mid,sa,se);
    else if(sa>mid)return qry(tr[x].rs,mid+1,r,sa,se);
    else{
        node ls=qry(tr[x].ls,l,mid,sa,mid);
        node rs=qry(tr[x].rs,mid+1,r,mid+1,se),ret;
        ret.sum=ls.sum+rs.sum;
        ret.lsum=max(ls.lsum,ls.sum+rs.lsum);
        ret.rsum=max(rs.rsum,rs.sum+ls.rsum);
        return ret;
    }
}
inline bool check(int x){
    node A,B,C;int sum=0;
    if(q[1]+1<=q[2]-1)B=qry(rt[x],1,n,q[1]+1,q[2]-1),sum+=B.sum;
    A=qry(rt[x],1,n,q[0],q[1]);sum+=A.rsum;
    C=qry(rt[x],1,n,q[2],q[3]);sum+=C.lsum;
    return sum>=0;
}
int main()
{
    freopen("pp.in","r",stdin);
    freopen("pp.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+n+1);
    num=unique(b+1,b+n+1)-b-1;
    for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+num+1,a[i])-b,id[a[i]]=i;
    build(rt[n+1],1,n);
    for(int i=n;i>=1;i--){
        rt[i]=rt[i+1];
        ins(rt[i],1,n,id[i]);
    }
    scanf("%d",&Q);
    while(Q--){
        for(int i=0;i<4;i++)scanf("%d",&q[i]),q[i]=(q[i]+ans)%n+1;
        sort(q,q+4);
        int l=1,r=num,mid,ret=0;
        while(l<=r){
            mid=(l+r)>>1;
            if(check(mid))ret=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%d\n",ans=b[ret]);
    }
    return 0;
}

bzoj 2653: middle

标签:body   post   i++   scanf   names   node   inline   std   else   

原文地址:https://www.cnblogs.com/Yuzao/p/8421542.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!