【BZOJ2653】Middle(主席树)

题面

BZOJ

洛谷

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

题解

陈老师神题啊,丽洁姐最神啦

还是二分答案

区间内的中位数大于一个值?

将大于答案的数赋值为\(1\),小于的赋值\(-1\)

既然是左端点在\([a,b]\),右端点在\([c,d]\)

那么也就是\([b+1,c-1]\)必须选

而现在要中位数尽可能大

所以要选的就是\([a,b]\)的最大右子段和

\([c,d]\)的最大左子段和

而答案一定是某个数列中的数

排序之后依次把自己位置上的\(1\)变成\(-1\)即可

不可能开这么多线段树

显然是在主席树上直接修改

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 22222
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Node
{
int lv,rv,sum;
int ls,rs,id;
}t[MAX<<6];
Node operator+(Node a,Node b)
{
Node c;
c.lv=max(a.lv,a.sum+b.lv);
c.rv=max(b.rv,b.sum+a.rv);
c.sum=a.sum+b.sum;
c.ls=a.id;c.rs=b.id;
return c;
}
int tot,rt[MAX];
void Build(int &x,int l,int r)
{
x=++tot;t[x].id=x;
if(l==r){t[x].lv=t[x].rv=t[x].sum=1;return;}
int mid=(l+r)>>1;
Build(t[x].ls,l,mid);Build(t[x].rs,mid+1,r);
t[x]=t[t[x].ls]+t[t[x].rs];t[x].id=x;
}
void Modify(int &x,int ff,int l,int r,int p,int w)
{
t[x=++tot]=t[ff];t[x].id=x;
if(l==r){t[x].lv=t[x].rv=t[x].sum=t[x].sum+w;return;}
int mid=(l+r)>>1;
if(p<=mid)Modify(t[x].ls,t[ff].ls,l,mid,p,w);
else Modify(t[x].rs,t[ff].rs,mid+1,r,p,w);
t[x]=t[t[x].ls]+t[t[x].rs];t[x].id=x;
}
Node Query(int x,int l,int r,int L,int R)
{
if(l==L&&r==R)return t[x];
int mid=(l+r)>>1;
if(R<=mid)return Query(t[x].ls,l,mid,L,R);
if(L>mid)return Query(t[x].rs,mid+1,r,L,R);
return Query(t[x].ls,l,mid,L,mid)+Query(t[x].rs,mid+1,r,mid+1,R);
}
int n,a[MAX],p[MAX];
bool cmp(int x,int y){return a[x]<a[y];}
int main()
{
n=read();
for(int i=1;i<=n;++i)a[i]=read();
for(int i=1;i<=n;++i)p[i]=i;
Build(rt[1],1,n);
sort(&p[1],&p[n+1],cmp);
for(int i=1;i<=n;++i)
Modify(rt[i+1],rt[i],1,n,p[i],-2);
sort(&a[1],&a[n+1]);
int Q=read();
int ans=0,q[5];
while(Q--)
{
for(int i=1;i<=4;++i)q[i]=(read()+ans)%n+1;
sort(&q[1],&q[5]);
int l=1,r=n,Ans=1;
while(l<=r)
{
int mid=(l+r)>>1,ss=0;
if(q[2]+1<=q[3]-1)ss+=Query(rt[mid],1,n,q[2]+1,q[3]-1).sum;
ss+=Query(rt[mid],1,n,q[1],q[2]).rv;
ss+=Query(rt[mid],1,n,q[3],q[4]).lv;
if(ss>=0)Ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans=a[Ans]);
}
return 0;
}

【BZOJ2653】Middle(主席树)的更多相关文章

  1. [BZOJ2653]middle 主席树+二分

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

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

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

  3. Luogu2839 Middle 主席树、二分答案

    题目传送门:https://www.luogu.org/problemnew/show/P2839 题目大意:给出一个长度为$N$的序列与$Q$次询问,每次询问左端点在$[a,b]$,右端点在$[c, ...

  4. bzoj 2653 middle(主席树)

    题面:https://vjudge.net/problem/HYSBZ-2653 博客:https://blog.csdn.net/litble/article/details/78984846 这个 ...

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

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

  6. BZOJ 2653: middle [主席树 中位数]

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

  7. BZOJ 2653: middle 主席树 二分

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

  8. BZOJ 2653 middle | 主席树

    题目: http://www.lydsy.com/JudgeOnline/problem.php?id=2653 题解: 设答案为ans,把大于等于ans的记为1,小于的记为-1,这样可以知道当前an ...

  9. 洛谷P2839 [国家集训队]middle 主席树_二分

    Code: #include <cstdio> #include <algorithm> #include <cstring> #include <strin ...

随机推荐

  1. 搜索引擎ElasticSearch系列(三): ElasticSearch2.4.4 bigdesk插件安装

    一:ElasticSearch bigdesk插件简介 bigdesk是elasticsearch的一个集群监控工具,可以通过它来查看es集群的各种状态,如:cpu.内存使用情况,索引数据.搜索情况, ...

  2. My status

    I haven‘t any one who is strong relationship with me. My skill is normal. I'm not interesting in neg ...

  3. selenium、unittest——POM框架并出报告

    学习隔壁大神的POM框架,结合自己的用例进行修改整理并执行,操作遇到的主要问题是如何分布的写各个模块并统一运行,每个文件夹想要import里面的模块需要有__init__模块 POM主要分为三个部分, ...

  4. sublime3配置java开发环境

    链接:http://www.jianshu.com/p/48a524a4f63c 或者:http://www.jianshu.com/p/9d167c4c4feb 侵权删!

  5. NO.1:自学tensorflow之路------神经网络背景知识

    引言 从本周,我将开始tensorflow的学习.手头只有一本<tensorflow:实战Google深度学习框架>,这本书对于tensorflow的入门有一定帮助.tensorflow中 ...

  6. C# 反射,动态编译

    反射是动态获取程序集的元数据的一种技术,这句话是做.NET程序员面试题目的一个的答案,你可选择记住它,就好比高中生物学里面讲到的细胞的结构的课程时,细胞由细胞膜,细胞质和细胞核组成.根据做程序的经验, ...

  7. spark RDD、DataFrame、DataSet之间的相互转化

    这三个数据集看似经常用,但是真正归纳总结的时候,很容易说不出来 三个之间的关系与区别参考我的另一篇blog  http://www.cnblogs.com/xjh713/p/7309507.html ...

  8. <力荐>非常好的正则表达式的详解<力荐>

    正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串.将匹配的子串做替换或者从某个串中取出符合某个条件的子串等. 列目录时, dir *.t ...

  9. 我是IT小小鸟读书笔记

    阅读了我是IT小小鸟后发现,自己开发程序是真的很苦难的,在现在这个空对空的时期,我们学习到大部分的全都是理论知识,而没有真正的去进行实践.没有经过实践,我们在程序开发过程中也就无法发现自身的困难. 在 ...

  10. C语言问卷调查表

    你对自己的未来有什么规划?做了哪些准备?    对未来比较迷茫,现在的主要任务是学好专业课 你认为什么是学习?学习有什么用?现在学习动力如何?为什么?   活到老学到老,学习是一辈子的事.在学习的过程 ...