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. regex & form validation & phone

    regex & form validation https://regexper.com/ https://gitlab.com/javallone/regexper-static https ...

  2. 【bzoj1878】[SDOI2009]HH的项链 树状数组

    题目描述 HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变得越来越长.有一 ...

  3. POJ——2449 Remmarguts' Date

    Description "Good man never makes girls wait or breaks an appointment!" said the mandarin ...

  4. ARC075 E.Meaningful Mean(树状数组)

    题目大意:给定n和k,问an中有多少子区间的平均值大于等于k 很巧妙的一个式子,就是如果一个区间[l, r]满足条件 那么则有 sum[r] - sum[l-1] >= (r-l+1)*k 整理 ...

  5. IIS 发布后无法连接数据库(应用池问题)

    查找网站对应的  应用池,修改为 .net4.0  然后设置启动32位应用程序为 True

  6. BZOJ1607 [Usaco2008 Dec]Patting Heads 轻拍牛头 【筛法】

    题目 今天是贝茜的生日,为了庆祝自己的生日,贝茜邀你来玩一个游戏. 贝茜让N(1≤N≤100000)头奶牛坐成一个圈.除了1号与N号奶牛外,i号奶牛与i-l号和i+l号奶牛相邻.N号奶牛与1号奶牛相邻 ...

  7. CentOS 7, Attempting to create directory /root/perl5

    By francis_hao    Apr 10,2017 在使用CentOS 7的时候,首次登陆会出现新建一个perl5文件夹的提示,删除该文件后,之后登陆还是会出现该提示并新建了perl5文件夹. ...

  8. css的padding,border,margin的意思

    下面的内边距(padding).边框(border) .外边距(margin)的意思是我自己的理解. 代码如下: <!DOCTYPE html> <html lang="e ...

  9. 记录一发wm_concat()函数排序的问题

    需求:需要将列转行之后的工序按照待执行工序号排序,如果一样按工序号排 解决方法如下: select part_no, max(ywggx) ywggx from(select mt.part_no , ...

  10. maven工程开启jetty调试

    转摘自:http://czj4451.iteye.com/blog/1942437 准备工作: a. 在pom.xml中配置jetty插件: <plugins> <plugin> ...