middle

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

 
题解:
  十分经典啊,好题,中位数的题目,以后可以想到二分去解决。
  就是比中位数大的变1,小的为-1,则sum>=0即可判断是否可以比当前二分的
  中位数更大,然后就可以,所以对于从小到大,开n个不同状态的线段树,这样就可以了。
 #include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstdio> #define lson tr[p].ls
#define rson tr[p].rs
#define N 20007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch>''||ch<''){if (ch=='-') f=-;ch=getchar();}
while(ch<=''&&ch>=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,m,sz,ans;
int a[N],id[N],rt[N];
struct Node
{
int sum,lmx,rmx,ls,rs;
}tr[N*]; bool cmp(int x1,int x2)
{
return a[x1]<a[x2];
}
void update(int p)
{
tr[p].sum=tr[lson].sum+tr[rson].sum;
tr[p].lmx=max(tr[lson].lmx,tr[lson].sum+tr[rson].lmx);
tr[p].rmx=max(tr[rson].rmx,tr[rson].sum+tr[lson].rmx);
}
void build(int &p,int l,int r)
{
p=++sz;
if (l==r)
{
tr[p].sum=tr[p].lmx=tr[p].rmx=;
return;
}
int mid=(l+r)>>;
build(tr[p].ls,l,mid),build(tr[p].rs,mid+,r);
update(p);
}
void build_new(int yl,int l,int r,int &xz,int val,int z)
{
xz=++sz;tr[xz]=tr[yl];
if (l==r)
{
tr[xz].lmx=tr[xz].rmx=tr[xz].sum=val;
return;
}
int mid=(l+r)>>;
if (z<=mid) build_new(tr[yl].ls,l,mid,tr[xz].ls,val,z);
else build_new(tr[yl].rs,mid+,r,tr[xz].rs,val,z);
update(xz);
}
int get_sum(int p,int l,int r,int x,int y)
{
if (l==x&&r==y) return tr[p].sum;
int mid=(l+r)>>;
if (y<=mid) return get_sum(tr[p].ls,l,mid,x,y);
else if (x>mid) return get_sum(tr[p].rs,mid+,r,x,y);
else return get_sum(tr[p].ls,l,mid,x,mid)+get_sum(tr[p].rs,mid+,r,mid+,y);
}
int get_rx(int p,int l,int r,int x,int y)
{
if (l==x&&r==y) return tr[p].lmx;
int mid=(l+r)>>;
if (y<=mid) return get_rx(tr[p].ls,l,mid,x,y);
else if (x>mid) return get_rx(tr[p].rs,mid+,r,x,y);
else return max(get_rx(tr[p].ls,l,mid,x,mid),get_sum(tr[p].ls,l,mid,x,mid)+get_rx(tr[p].rs,mid+,r,mid+,y));
}
int get_lx(int p,int l,int r,int x,int y)
{
if (l==x&&r==y) return tr[p].rmx;
int mid=(l+r)>>;
if (y<=mid) return get_lx(tr[p].ls,l,mid,x,y);
else if (x>mid) return get_lx(tr[p].rs,mid+,r,x,y);
else return max(get_lx(tr[p].rs,mid+,r,mid+,y),get_sum(tr[p].rs,mid+,r,mid+,y)+get_lx(tr[p].ls,l,mid,x,mid));
}
bool check(int k,int a,int b,int c,int d)
{
int sum=;
if (b+<=c-) sum+=get_sum(rt[k],,n,b+,c-);
sum+=get_lx(rt[k],,n,a,b);
sum+=get_rx(rt[k],,n,c,d);
return sum>=;//大的个数多的话那么可以找更大的中位数、
}
int main()
{
n=read();
for (int i=;i<=n;i++)
a[i]=read(),id[i]=i;
sort(id+,id+n+,cmp);
build(rt[],,n);
for (int i=;i<=n;i++)
build_new(rt[i-],,n,rt[i],-,id[i-]);
int qz[];
m=read();
while(m--)
{
qz[]=read(),qz[]=read(),qz[]=read(),qz[]=read();
for (int i=;i<=;i++)
qz[i]=(qz[i]+ans)%n;
for (int i=;i<=;i++)
qz[i]+=;
sort(qz+,qz++);
int l=,r=n,mid;
while(l<r)
{
mid=(l+r+)>>;
if (check(mid,qz[],qz[],qz[],qz[])) l=mid;
else r=mid-;
}
ans=a[id[l]];
printf("%d\n",ans);
}
}

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. 【BZOJ-2653】middle 可持久化线段树 + 二分

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

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

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

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

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

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

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

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

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

  9. bzoj 2653 middle 二分答案 主席树判定

    判断中位数是否可行需要将当前的解作为分界,大于其的置为1,小于为-1,然后b-c必选,ab,cd可不选,这个用线段树判定就好 但不能每次跑,所以套主席树,按权值排序,构建主席树,更新时将上一个节点改为 ...

  10. bzoj 2653 二分答案+可持久化线段树

    首先离散化,然后我们知道如果对于一个询问的区间[l1,r1],[l2,r2],我们二分到一个答案x,将[l1,r2]区间中的元素大于等于x的设为1,其余的设为-1,那么如果[l1,r1]的最大右区间和 ...

随机推荐

  1. 【LeetCode】297. Serialize and Deserialize Binary Tree

    二叉树的序列化与反序列化. 如果使用string作为媒介来存储,传递序列化结果的话,会给反序列话带来很多不方便. 这里学会了使用 sstream 中的 输入流'istringstream' 和 输出流 ...

  2. 在Windows7下编译调试C#程序

    要在 命令行下编译C#代码,要配置一下 1.在环境变量下新建一个变量 参数名: csc 参数值:C:\Windows\Microsoft.NET\Framework\v4.0.30319 2.在系统变 ...

  3. nginx负载均衡浅析

    熟悉Nginx的小伙伴都知道,Nginx是一个非常好的负载均衡器.除了用的非常普遍的Http负载均衡,Nginx还可以实现Email,FastCGI的负载均衡,甚至可以支持基于Tcp/UDP协议的各种 ...

  4. (转)淘淘商城系列——使用maven tomcat插件启动聚合工程

    http://blog.csdn.net/yerenyuan_pku/article/details/72672389 上文我们一起学习了如何使用maven tomcat插件来启动web工程,本文我们 ...

  5. Mac OS 使用asio库

    下载地址:http://sourceforge.net/projects/asio/files/asio/1.12.2%20%28Stable%29/ 本人下载的版本:asio-1.12.2 1,本人 ...

  6. CAD参数绘制mcdbsolid对象(com接口)

    C#中实现代码说明: private void DrawSolid() { //绘McDbSolid对象 axMxDrawX1.AddLinetype("MLineType1", ...

  7. java_String类的功能

    String类使用了final修饰不能被继承 实现类Serializable接口,字符串支持序列化 实现了Comparable接口,字符串可以比较大小 内部定义final char[] value用于 ...

  8. 【软件构造】(转)Java中的comparable和comparator

    为了方便阅读和复习,转载至此,原地址:温布利往事的博客 阅读目录 一.Comparable简介 二.Comparator简介 三.Comparable和Comparator区别比较 回到顶部 一.Co ...

  9. 启动myeclipse弹窗Please allow Subclipse team to receive anonymous usage statistics for this Eclipse intance

    Please allow Subclipse team to receive anonymous usage statistics for this Eclipse intance(翻译:请允许Sub ...

  10. Java随机数使用

    JAVA取随机数的三种方式: Math.random() System.currentTimeMillis() random.nextInt() 废话不多说,看代码: /** *取单个随机数 *Mat ...