【BZOJ2653】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
271451044
271451044
969056313

Sample Output

HINT

0:n,Q<=100
1,...,5:n<=2000
0,...,19:n<=20000,Q<=25000

题解:好吧这题不看题解还真的很难想~

首先二分中位数还是挺好像的,但问题是怎么判断一个中位数是否可行。一个中位数mid可行的条件是序列中(≥mid的数的个数)≥(<mid的数的个数),也就是说,我们将比≥mid的数看成1,<mid的数看成-1,那么需要存在一段区间,使得区间和非负。这又和可持久化线段树有什么关系呢?

我们将所有数排序,然后令1-n的初值都是1,然后将n个数从小到大扔到可持久化线段树中去,并将对应位置变成-1,这样就很好的满足了所给条件。现在问题就是如何判断[a,b]-[c,d]中有没有符合条件的区间,只需要对线段树维护区间连续子段和,最大连续前缀子段和,最大后缀子段和,然后搞一搞就行了。(小白逛公园的简化)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=20010;
int n,m,maxx,minn,tot,ans;
struct sag
{
int ls,rs,sum,lm,rm,sm;
}s[maxn*1000];
struct node
{
int num,org;
}p[maxn];
int q[10],rt[maxn];
int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int max(int a,int b,int c)
{
return max(max(a,b),c);
}
void pushup(int x)
{
s[x].lm=max(s[s[x].ls].lm,s[s[x].ls].sum+s[s[x].rs].lm,0);
s[x].rm=max(s[s[x].rs].rm,s[s[x].rs].sum+s[s[x].ls].rm,0);
s[x].sm=max(s[s[x].ls].sm,s[s[x].rs].sm,s[s[x].ls].rm+s[s[x].rs].lm);
s[x].sum=s[s[x].ls].sum+s[s[x].rs].sum;
}
void build(int l,int r,int &x)
{
if(!x) x=++tot;
if(l==r)
{
s[x].sum=s[x].sm=s[x].lm=s[x].rm=1;
return;
}
int mid=l+r>>1;
build(l,mid,s[x].ls),build(mid+1,r,s[x].rs);
pushup(x);
}
void insert(int x,int &y,int l,int r,int pos)
{
if(r<pos) return ;
y=++tot;
if(l==r)
{
s[y].sum=-1,s[y].lm=s[y].rm=s[y].sm=0;
return ;
}
int mid=l+r>>1;
if(pos<=mid) s[y].rs=s[x].rs,insert(s[x].ls,s[y].ls,l,mid,pos);
else s[y].ls=s[x].ls,insert(s[x].rs,s[y].rs,mid+1,r,pos);
pushup(y);
}
bool cmp(node a,node b)
{
return a.num<b.num;
}
int qs(int l,int r,int x,int a,int b)
{
if(a>b) return 0;
if(a<=l&&r<=b) return s[x].sum;
int mid=l+r>>1;
if(b<=mid) return qs(l,mid,s[x].ls,a,b);
if(a>mid) return qs(mid+1,r,s[x].rs,a,b);
return qs(l,mid,s[x].ls,a,b)+qs(mid+1,r,s[x].rs,a,b);
}
int ql(int l,int r,int x,int a,int b)
{
if(a>b) return 0;
if(a<=l&&r<=b) return s[x].rm;
int mid=l+r>>1;
if(b<=mid) return ql(l,mid,s[x].ls,a,b);
if(a>mid) return ql(mid+1,r,s[x].rs,a,b);
return max(ql(l,mid,s[x].ls,a,b)+qs(mid+1,r,s[x].rs,a,b),ql(mid+1,r,s[x].rs,a,b));
}
int qr(int l,int r,int x,int a,int b)
{
if(a>b) return 0;
if(a<=l&&r<=b) return s[x].lm;
int mid=l+r>>1;
if(b<=mid) return qr(l,mid,s[x].ls,a,b);
if(a>mid) return qr(mid+1,r,s[x].rs,a,b);
return max(qr(mid+1,r,s[x].rs,a,b)+qs(l,mid,s[x].ls,a,b),qr(l,mid,s[x].ls,a,b));
}
int solve(int sta)
{
int a=ql(1,n,rt[sta-1],q[0],q[1]-1);
int b=qs(1,n,rt[sta-1],q[1],q[2]);
int c=qr(1,n,rt[sta-1],q[2]+1,q[3]);
if(a+b+c>=0) return 1;
return 0;
}
int main()
{
n=rd();
int i,j,l,r,mid;
for(i=1;i<=n;i++) p[i].num=rd(),p[i].org=i,maxx=max(maxx,p[i].num),minn=min(minn,p[i].num);
build(1,n,rt[0]);
sort(p+1,p+n+1,cmp);
for(i=1;i<=n;i++) insert(rt[i-1],rt[i],1,n,p[i].org);
m=rd();
for(i=1;i<=m;i++)
{
for(j=0;j<4;j++) q[j]=(rd()+ans)%n+1;
sort(q+0,q+4);
l=1,r=n+1;
while(l<r)
{
mid=l+r>>1;
if(solve(mid)) l=mid+1;
else r=mid;
}
ans=p[l-1].num;
printf("%d\n",ans);
}
return 0;
}

【BZOJ2653】middle 二分+可持久化线段树的更多相关文章

  1. BZOJ 4556(后缀数组+主席树求前驱后继+二分||后缀数组+二分+可持久化线段树)

    换markdown写了.. 题意: 给你一个1e5的字符串,1e5组询问,求\([l_1,r_1]\)的所有子串与\([l_2,r_2]\)的lcp 思路: 首先可以发现答案是具有单调性的,我们考虑二 ...

  2. 【XSY2720】区间第k小 整体二分 可持久化线段树

    题目描述 给你你个序列,每次求区间第\(k\)小的数. 本题中,如果一个数在询问区间中出现了超过\(w\)次,那么就把这个数视为\(n\). 强制在线. \(n\leq 100000,a_i<n ...

  3. bzoj 2653 middle (可持久化线段树)

    middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1981  Solved: 1097[Submit][Status][Discuss] D ...

  4. 【BZOJ-2653】middle 可持久化线段树 + 二分

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1298  Solved: 734[Submit][Status][Discu ...

  5. [BZOJ 2653] middle(可持久化线段树+二分答案)

    [BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...

  6. BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)

    BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...

  7. 【bzoj2653】middle 可持久化线段树区间合并

    题目描述 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[ ...

  8. 洛谷P3994 Highway(树形DP+斜率优化+可持久化线段树/二分)

    有点类似NOI2014购票 首先有方程$f(i)=min\{f(j)+(dep_i-dep_j)*p_i+q_i\}$ 这个显然是可以斜率优化的... $\frac {f(j)-f(k)}{dep_j ...

  9. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

随机推荐

  1. 阿里云web播放器

    原文地址:https://help.aliyun.com/document_detail/51991.html?spm=5176.doc61109.6.703.ZTCYoi 一.概念说明 1. pla ...

  2. VSCode集成Git代码管理

    一.安装和配置VSCode与Git 1.下载Git并安装: https://git-scm.com/download/ 2.下载VSCode并进行安装: https://code.visualstud ...

  3. Android Studio公布到Jcenter

    1.前言 拥抱开源.热爱开源,将我们觉得不错的代码开源到gihtub.将我们的库公布到jcenter\mevan等. 2.准备工作 2.1 准备 申请仓库账号 注意model为android libr ...

  4. Openresty配置文件上传下载

    1. 下载包安装Openresty openresty-1.13.6.1下载地址 https://openresty.org/download/openresty-1.13.6.1.tar.gz 安装 ...

  5. myeclipse能启动tomcat但是用startup.bat无法启动

    myeclipse能启动tomcat但是用startup.bat无法启动 这个问题困扰了我一天,把一天的周末时间白白花费了.各种百度,各种尝试都没办法解决.在江湖上闯,难道就只有百度一招吗? 不是,我 ...

  6. vue 过渡效果-列表过渡

    到目前为止,关于过渡我们已经讲到, 单个节点 同一时间渲染多个节点的一个 那么怎么同时渲染整个列表,比如使用v-if?在这种场景下,使用<transition-group>组件,在我们深入 ...

  7. Freemarker自定义方法

    在项目中有一个需求,每个物品有一个guid,存在数据库中,而在页面上需要显示一个对应的业务数据值,暂且叫做serverId,serverId是通过guid移位计算得来.serverId只需要显示,后台 ...

  8. AdapterView 和 RecyclerView 的连续滚动

    AdapterView 和 RecyclerView 的连续滚动 android RecyclerView tutorial 概述 ListView 和 GridView 的实现方式 Recycler ...

  9. [转载] 关于mkvtoolnix批量处理的

    需要的工具:mkvtoolnix.记事本 案例介绍:用文件A的视频+文件B的音频+字幕合成新MKV,在文件列表中,按A.B.C顺序排列.其中A与B都是Mkv格式,所以A与B不能放在同一个文件夹中(就算 ...

  10. matlab和c++混合编程---matlab和vs的环境配置问题及方法和步骤(转载)

    matlab和c++混合编程---方法和步骤 matlab和c++混合编程---matlab和vs的环境配置问题 摘要:Matlab具有很强的数值计算和分析等能力,而C/C++是目前最为流行的高级程序 ...