您的位置:首页 > 其它

【主席树】BZOJ 2653 middle

2016-01-12 19:47 344 查看

BZOJ 2653 middle

Description

 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。

 给你一个长度为n的序列s。

 回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。

 其中a < b< c < d。

 位置也从0开始标号。

 我会使用一些方式强制你在线。

Input

 第一行序列长度n。

 接下来n行按顺序给出a中的数。

 接下来一行Q。

 然后Q行每行a,b,c,d,我们令上个询问的答案是x(如果这是第一个询问则x=0)。

 令数组q={(a+x)%n,(b+x)%n,(c+x)%n,(d+x)%n}。

 将q从小到大排序之后,令真正的要询问的a=q[0],b=q[1],c=q[2],d=q[3]。

 输入保证满足条件。

Output

Q行依次给出询问的答案。

Sample Input

5

170337785

271451044

22430280

969056313

206452321

3

3 1 0 2

2 3 1 4

3 1 4 0

Sample Output

271451044

271451044

969056313

HINT

0:n,Q<=100

1,…,5:n<=2000

0,…,19:n<=20000,Q<=25000

Solution

口胡了一个算法不对。。

只能去看题解

算法很巧妙

对于一个x,比它大的权值设为1,小的权值设为-1.

然后树一路建过去

询问的时候先二分答案

然后判定可行性

求区间最大子段和,大于0则可行

维护一下lx,rx就可以了

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>

using namespace std;

#define maxn 20001

struct ha{
int v,l,r,lx,rx;
}t[maxn*20];

struct ope{
int v,id;
}op[maxn];

int size,q[5],n,root[maxn];

bool cmp(const ope A,const ope B)
{
return A.v<B.v;
}

inline int in()
{
int x=0;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
return x;
}

void insert(int &poi,int l,int r,int k,int d)
{
t[++size]=t[poi];poi=size;
t[poi].v+=d;
if(l==r){
t[poi].lx=t[poi].rx=-1;
return;
}
int mid=(l+r)>>1;
if(mid>=k)insert(t[poi].l,l,mid,k,d);
else insert(t[poi].r,mid+1,r,k,d);
t[poi].lx=max(t[t[poi].l].lx,t[t[poi].r].lx+t[t[poi].l].v);
t[poi].rx=max(t[t[poi].r].rx,t[t[poi].l].rx+t[t[poi].r].v);
}

int qm(int x,int l,int r,int L,int R)
{
if(l>L||r<R||L>R)return 0;
int mid=(l+r)>>1;
if(l==L&&r==R)return t[x].v;
else if(mid<R && mid>=L)return qm(t[x].l,l,mid,L,mid)+qm(t[x].r,mid+1,r,mid+1,R);
else if(mid<L)return qm(t[x].r,mid+1,r,L,R);
else if(mid>=R)return qm(t[x].l,l,mid,L,R);
}

int ql(int x,int l,int r,int L,int R)
{
if(l>L||r<R||L>R)return -9999999;
int mid=(l+r)>>1;
if(l==L&&R==r)return t[x].lx;
else if(mid<R && mid>=L)return max(ql(t[x].l,l,mid,L,mid),qm(t[x].l,l,mid,L,mid)+ql(t[x].r,mid+1,r,mid+1,R));
else if(mid<L)return ql(t[x].r,mid+1,r,L,R);
else if(mid>=R)return ql(t[x].l,l,mid,L,R);
}

int qr(int x,int l,int r,int L,int R)
{
if(l>L||r<R||L>R)return -9999999;
int mid=(l+r)>>1;
if(l==L&&R==r)return t[x].rx;
else if(mid<R && mid>=L)return max(qr(t[x].r,mid+1,r,mid+1,R),qm(t[x].r,mid+1,r,mid+1,R)+qr(t[x].l,l,mid,L,mid));
else if(mid<L)return qr(t[x].r,mid+1,r,L,R);
else if(mid>=R)return qr(t[x].l,l,mid,L,R);
}

bool check(int num)
{
int L,R,M;
L=qr(root[num],1,n,q[1],q[2]);
M=qm(root[num],1,n,q[2]+1,q[3]-1);
R=ql(root[num],1,n,q[3],q[4]);
return L+M+R>=0;
}

int div2()
{
int l=1,r=n,an;
while(l<r)
{
int mid=(l+r+1)>>1;
if(check(mid))l=mid;
else r=mid-1;
}
return l;
}

void build(int l,int r,int &k)
{
k=++size;
t[k].v=r-l+1;
if(l==r)
{
t[k].lx=t[k].rx=1;
return;
}
int mid=(l+r)>>1;
build(l,mid,t[k].l);
build(mid+1,r,t[k].r);
t[k].lx=max(t[t[k].l].lx,t[t[k].r].lx+t[t[k].l].v);
t[k].rx=max(t[t[k].r].rx,t[t[k].l].rx+t[t[k].r].v);
}

int main()
{
freopen("2653.in","r",stdin);
n=in();
for(int i=1;i<=n;i++)
op[i].v=in(),op[i].id=i;
sort(1+op,1+op+n,cmp);
build(1,n,root[1]);
for(int i=2;i<=n;i++)
{
root[i]=root[i-1];
insert(root[i],1,n,op[i-1].id,-2);
}
int m=in(),ans=0;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=4;j++)
q[j]=(in()+ans)%n+1;
sort(1+q,1+q+4);
ans=op[div2()].v;
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: