2653: middle

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 2042  Solved: 1123
[Submit][Status][Discuss]

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

Source

我们二分中位数,对于大于mid的数赋值为1,小于mid的数为-1。若最大的区间和大于0则可行。

考虑建一颗主席树(维护权值线段树),root[i]为中位数为i时的前缀树。

二分查询即可。

 #include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define maxn 20005
#define ls(i) t[i].s[0]
#define rs(i) t[i].s[1]
using namespace std;
int read() {
int x=,f=;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-;
for(;isdigit(ch);ch=getchar()) x=x*+ch-'';
return x*f;
}
struct tmp {
int v,id;
bool operator <(const tmp tt) const {return v<tt.v;}
}a[maxn];
struct data {
int lm,rm,sum,s[];
}t[maxn*];
int n,q,sz;
int root[maxn];
void pushup(int x) {
t[x].lm=max(t[ls(x)].lm,t[ls(x)].sum+t[rs(x)].lm);
t[x].rm=max(t[rs(x)].rm,t[rs(x)].sum+t[ls(x)].rm);
t[x].sum=t[rs(x)].sum+t[ls(x)].sum;
}
void build(int &rt,int l,int r) {
rt=++sz;
if(l==r) {t[rt].sum=t[rt].lm=t[rt].rm=;return;}
int mid=l+r>>;
build(ls(rt),l,mid);build(rs(rt),mid+,r);
pushup(rt); }
void update(int p,int &rt,int l,int r,int x) {
rt=++sz;
t[rt]=t[p];
if(l==r) {t[rt].sum=-;t[rt].lm=t[rt].rm=;return;}
int mid=l+r>>;
if(x<=mid) update(ls(p),ls(rt),l,mid,x);
else update(rs(p),rs(rt),mid+,r,x);
pushup(rt);
}
int qs(int rt,int l,int r,int x,int y) {
if(x>y) return ;
if(l>=x&&r<=y) return t[rt].sum;
int mid=l+r>>,ans=;
if(x<=mid) ans+=qs(ls(rt),l,mid,x,y);
if(y>mid) ans+=qs(rs(rt),mid+,r,x,y);
return ans;
}
int ql(int rt,int l,int r,int x,int y) {
if(x>y) return ;
if(l>=x&&r<=y) return t[rt].lm;
int mid=l+r>>,ans=;
if(x<=mid) ans=max(ql(ls(rt),l,mid,x,y),ans);
if(y>mid) ans=max(qs(ls(rt),l,mid,x,mid)+ql(rs(rt),mid+,r,x,y),ans);
return ans;
}
int qr(int rt,int l,int r,int x,int y) {
if(x>y) return ;
if(l>=x&&r<=y) return t[rt].rm;
int mid=l+r>>,ans=;
if(x<=mid) ans=max(qs(rs(rt),mid+,r,mid+,y)+qr(ls(rt),l,mid,x,y),ans);
if(y>mid) ans=max(qr(rs(rt),mid+,r,x,y),ans);
return ans;
}
bool check(int x,int q1,int q2,int q3,int q4) {
int s=qs(root[x],,n-,q2,q3)+ql(root[x],,n-,q3+,q4)+qr(root[x],,n-,q1,q2-);
return s>=;
}
int main() {
t[].sum=t[].lm=t[].rm=;
n=read();
for(int i=;i<n;i++) a[i].v=read(),a[i].id=i;
sort(a,a+n);
build(root[],,n-);
for(int i=;i<n;i++) update(root[i-],root[i],,n-,a[i-].id);
int ans=;
q=read();
for(int i=;i<=q;i++) {
int ask[];
for(int j=;j<=;j++) ask[j]=(read()+ans)%n;
sort(ask+,ask+);
int L=,R=n-;
while(L<=R) {
int mid=L+R>>;
if(check(mid,ask[],ask[],ask[],ask[])) L=mid+;
else R=mid-;
}
ans=a[L-].v;
printf("%d\n",ans);
}
}

[BZOJ2653]middle 主席树+二分的更多相关文章

  1. bzoj 2653: middle (主席树+二分)

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2522  Solved: 1434[Submit][Status][Disc ...

  2. BZOJ 2653: middle(主席树+二分答案)

    传送门 解题思路 首先可以想到一种暴力做法,就是询问时二分,然后大于等于这个值的设为1,否则设为-1,然后就和GSS1那样统计答案.但是发现这样时间空间复杂度都很爆炸,所以考虑预处理,可以用主席树来做 ...

  3. BZOJ 2653: middle 主席树 二分

    https://www.lydsy.com/JudgeOnline/problem.php?id=2653 因为是两个方向向外延伸所以不能对编号取前缀和(这里只有前缀和向后传递的性质,不是实际意义的和 ...

  4. 2018湘潭邀请赛C题(主席树+二分)

    题目地址:https://www.icpc.camp/contests/6CP5W4knRaIRgU 比赛的时候知道这题是用主席树+二分,可是当时没有学主席树,就连有模板都不敢套,因为代码实在是太长了 ...

  5. BZOJ.1926.[SDOI2010]粟粟的书架(前缀和 主席树 二分)

    题目链接 题意: 在给定矩形区域内找出最少的数,满足和>=k.输出数的个数.两种数据范围. 0~50 注意到(真没注意到...)P[i,j]<=1000,我们可以利用前缀和预处理. num ...

  6. 计蒜客 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 ...

  7. HDU - 4866 主席树 二分

    题意:在x轴\([1,X]\)内的上空分布有n个占据空间\([L_i,R_i]\),高度\(D_i\)的线段,射中线段的得分为其高度,每次询问从x轴的\(x\)往上空射的最近k个线段的总得分,具体得分 ...

  8. POJ 6621: K-th Closest Distance(主席树 + 二分)

    K-th Closest Distance Time Limit: 20000/15000 MS (Java/Others)    Memory Limit: 524288/524288 K (Jav ...

  9. HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)

    HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分) 传送门:http://acm.hdu.edu.cn/showproblem.php? ...

随机推荐

  1. onkeypress,onkeyup,onkeydown区别

    onkeypress 这个事件在用户按下并放开任何字母数字键时发生.系统按钮(例如,箭头键和功能键)无法得到识别. onkeyup 这个事件在用户放开任何先前按下的键盘键时发生. onkeydown ...

  2. 【工具学习】——Maven的安装与配置

    [含义] 什么是构建? 构建,英文build.构建包括编译.运行.生成文档.打包.部署等等工作内容,如果我们每天手工去干这些事情,那会浪费很多的时间.因此,构建管理工具应运而生. maven,作为项目 ...

  3. intelliJ idea 使用技巧&方法

    导入的项目查看svn地址:在项目上右键--subversion--relocate可以看到以前对应的svn地址. 重要的几个快捷键的使用方式: (1)       alt+insert 成员变量封装 ...

  4. coredump分析

    首先通过命令 gdb freeswitch core.60954进入gdb. 这里freeswitch 是产生coredump的可执行应用,core.60954是应用产生的coredump文件. 然后 ...

  5. 在程序内部跳转到下一个页面 和 向另一个servlet发起跳转

    request.getRequestDispatcher("/success.html").forward(request,response); request.getReques ...

  6. Lua学习笔记:面向对象

    Lua学习笔记:面向对象 https://blog.csdn.net/liutianshx2012/article/details/41921077 Lua 中只存在表(Table)这么唯一一种数据结 ...

  7. 利用npm安装/删除/发布/更新/撤销发布包

    利用npm安装/删除/发布/更新/撤销发布包 什么是npm? npm是javascript的包管理工具,是前端模块化下的一个标志性产物 简单地地说,就是通过npm下载模块,复用已有的代码,提高工作效率 ...

  8. 【BZOJ 3907】网格 组合数学

    大家说他是卡特兰数,其实也不为过,一开始只是用卡特兰数来推这道题,一直没有怼出来,后来发现其实卡特兰数只不过是一种组合数学,我们可以退一步直接用组合数学来解决,这道题运用组合数的思想主要用到补集与几何 ...

  9. vector 进阶

    http://classfoo.com/ccby/article/jnevK #include <iostream> #include <vector> #include &l ...

  10. 理解[].forEach.call()

    例子: let cols = document.querySelectorAll('ul li') [].forEach.call(cols, function (col, index) { // T ...