2653: middle

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1298  Solved: 734
[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

Sample Output

271451044
271451044
969056313

HINT

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

Source

Solution

这道题思路相当妙啊

自己一开始看错题了,以为就是求中位数,那么显然长度为奇数时就是中间那个,长度为偶数时可能是实数,根本没法搞...

然后有一种想法很显然,就是可以通过先求出$[b,c]$段的中位数,然后贪心的从$b$到$a$,从$c$到$d$扩展这个序列,然后搞。

可是这样本质上就是暴力,所以显然不行。

以前遇到的中位数有一种很常规的搞法,就是假设中位数为$x$,那么把$<x$的赋值$-1$,把$>=x$的赋值$+1$,然后看看是否有连续的一段$Sum>=0$

这种方法显然是具有单调性的,所以又可以把枚举$x$的复杂度降到$O(logN)$

然后可以用线段树去维护连续的子段和,再维护一下左右端点,保证左右端点分别在$[a,b]$和$[c,d]$之间即可,但是这样的线段树每次需要重建,所以复杂度还是偏大。

可以考虑利用可持久化线段树,对于假定的中位数$x$,所有比他小的数为$-1$,而比他大的仍为$1$,这样就可以先建出一棵全$1$的树,然后每次再建一条$-1$的链,查询的时候前面的用$-1$,后面的用$1$,就可以达到要求了。

总复杂度$O(Qlog^{2}N)$

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int x=; char ch=getchar();
while (ch<'' || ch>'') ch=getchar();
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x;
}
#define MAXN 200010
int N,a[MAXN],Q,last;
namespace PrTree
{
int lson[MAXN*],rson[MAXN*],root[MAXN],sum[MAXN*],left[MAXN*],right[MAXN*],sz;
inline void Update(int now)
{
sum[now]=sum[lson[now]]+sum[rson[now]];
left[now]=max(left[lson[now]],sum[lson[now]]+left[rson[now]]);
right[now]=max(right[rson[now]],sum[rson[now]]+right[lson[now]]);
}
inline void BuildTree(int l,int r,int &now)
{
now=++sz;
if (l==r) {left[now]=right[now]=sum[now]=; return;}
int mid=(l+r)>>;
BuildTree(l,mid,lson[now]); BuildTree(mid+,r,rson[now]);
Update(now);
}
inline void Insert(int l,int r,int &now,int fa,int pos,int val)
{
now=++sz;
if (l==r) {sum[now]=left[now]=right[now]=val; return;}
lson[now]=lson[fa],rson[now]=rson[fa];
int mid=(l+r)>>;
if (pos<=mid) Insert(l,mid,lson[now],lson[fa],pos,val);
else Insert(mid+,r,rson[now],rson[fa],pos,val);
Update(now);
}
inline int Query(int l,int r,int L,int R,int now)
{
if (L>R) return ;
if (L<=l && R>=r) return sum[now];
int mid=(l+r)>>,re=;
if (L<=mid) re+=Query(l,mid,L,R,lson[now]);
if (R>mid) re+=Query(mid+,r,L,R,rson[now]);
return re;
}
inline int Left(int l,int r,int L,int R,int now)
{
if (L>R) return ;
if (L==l && R==r) return left[now];
int mid=(l+r)>>;
if (R<=mid) return Left(l,mid,L,R,lson[now]);
else if (L>mid) return Left(mid+,r,L,R,rson[now]);
else return max(Left(l,mid,L,mid,lson[now]),Query(l,mid,L,mid,lson[now])+Left(mid+,r,mid+,R,rson[now]));
}
inline int Right(int l,int r,int L,int R,int now)
{
if (L>R) return ;
if (L==l && R==r) return right[now];
int mid=(l+r)>>;
if (R<=mid) return Right(l,mid,L,R,lson[now]);
else if (L>mid) return Right(mid+,r,L,R,rson[now]);
else return max(Right(mid+,r,mid+,R,rson[now]),Query(mid+,r,mid+,R,rson[now])+Right(l,mid,L,mid,lson[now]));
}
}using namespace PrTree;
int q[],id[MAXN];
inline bool Check(int x)
{
int a=q[],b=q[],c=q[],d=q[];
return Query(,N,b,c,root[x])+max(Right(,N,a,b-,root[x]),)+max(Left(,N,c+,d,root[x]),)>=;
}
inline bool cmp(int x,int y) {return a[x]<a[y];}
int main()
{
N=read();
for (int i=; i<=N; i++) a[i]=read(),id[i]=i;
stable_sort(id+,id+N+,cmp); stable_sort(a+,a+N+);
BuildTree(,N,root[]);
for (int i=; i<=N; i++) PrTree::Insert(,N,root[i],root[i-],id[i-],-);
Q=read();
while (Q--)
{
for (int i=; i<=; i++) q[i]=(read()+last)%N+;
stable_sort(q+,q++);
int l=,r=N,mid;
while (l<=r)
{
mid=(l+r)>>;
if (Check(mid)) l=mid+; else r=mid-;
}
printf("%d\n",last=a[l-]);
}
return ;
}

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

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

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

  2. BZOJ 2653 middle (可持久化线段树+中位数+线段树维护最大子序和)

    题意: 左端点在[a,b],右端点在[c,d],求这个线段里中位数(上取整)最大值 思路: 对数组离散化,对每一个值建中位数的可持久化线段树(有重复也没事),就是对于root[i],大于等于i的值为1 ...

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

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

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

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

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

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

  6. 【Codechef FRBSUM】【FJOI2016】【BZOJ4299】【BZOJ 4408】 可持久化线段树

    4408: [Fjoi 2016]神秘数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 475  Solved: 287[Submit][Status ...

  7. BZOJ - 3123 森林 (可持久化线段树+启发式合并)

    题目链接 先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树.当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组.树的结点数可以用并查集来维护 ...

  8. BZOJ 4552: [Tjoi2016&Heoi2016]排序 线段树 二分

    目录 此代码是个假代码,只能糊弄luogu,以后再改,路过大佬也可以帮一下辣 update 10.6 此代码是个假代码,只能糊弄luogu,以后再改,路过大佬也可以帮一下辣 /* //fang zhi ...

  9. bzoj 3653: 谈笑风生 可持久化线段树

    题目大意 在一棵单位边权的有根树上支持询问: 给定a,k求满足下列条件的有序三元对的个数. a,b,c互不相同 a,b均为c的祖先 a,b树上距离<=k 题解 solution 1 首先我们知道 ...

随机推荐

  1. python 学习笔记 -logging模块(日志)

    模块级函数 logging.getLogger([name]):返回一个logger对象,如果没有指定名字将返回root loggerlogging.debug().logging.info().lo ...

  2. JS定时刷新页面及跳转页面

    JS定时刷新页面及跳转页面 Javascript 返回上一页1. Javascript 返回上一页 history.go(-1), 返回两个页面: history.go(-2); 2. history ...

  3. Angular的自定义指令以及实例

    本文章已收录于:  AngularJS知识库  分类: javascript(55)  http://www.cnblogs.com/xiaoxie53/p/5058198.html   前面的文章介 ...

  4. 菜鸟快飞之JavaScript函数

    1.复制变量值 在说函数前,我觉得需要先说说关于变量值的复制,以便后面的理解. 复制基本类型的值: 当一个变量复制另外一个值为基本类型的变量时,两个变量可以参与任何操作而不会互相影响 var num1 ...

  5. 5.2 Array类型介绍

    Array类型是数组类型,Array(数组)类型也是引用类型中的一种. js 数组中的每一项可以保存任何类型的数据. js数组的大小/长度是可以动态调整的.如果你往数组中添加数据,数组长度会自动增加. ...

  6. 大数据下BI产品如何发挥最大价值

    看到这个题目,你是否总感觉云里雾里?你是否真正懂什么叫“大数据”?商业智能BI和大数据又有着什么千丝万缕的联系?为什么说商业智能BI能在大数据中发挥价值? 大数据,指的是所涉及的数据资料量规模巨大到无 ...

  7. Android Weekly Notes Issue #218

    Android Weekly Issue #218 August 14th, 2016 http://androidweekly.net/issues/issue-218 ARTICLES & ...

  8. react-native DatePicker日期选择组件的实现

    本教程的实现效果如下: 为了实现其淡入/淡出的覆盖效果, 还有取消按钮, 在此用了一个三方的组件, 大家可以先安装一下: 三方组件的地址:https://github.com/eyaleizenber ...

  9. Entity Framework之IQueryable和list本地集合

    我们来说一下Iqueryable集合和List等本地集合的区别,下面我们通过建立一个简单的例子来学习这个知识点,直接进入主题吧 1.首先对比一下两段代码?看一下有什么结果: (1) 第一段代码如图所示 ...

  10. 关于在安装MySQL时报错"本地计算机上的mysql服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止"的解决方法

    首先将你下载的MySQL安装或者解压(对应安装版和解压版),下载地址http://dev.mysql.com/downloads/mysql/ 然后复制你安装目录中的my-default.ini,更改 ...