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. JS 事件添加onclick写法注意。

    自定义函数添加onclick事件写法注意. 错误写法:element.onclick = addclass(className); 正确写法:element.onclick = function(){ ...

  2. 窗体WINFORM

    窗体的事件:删除事件:先将事件页面里面的挂好的事件删除,再删后台代码里面的事件 Panel是一个容器 1.Label -- 文本显示工具Text:显示的文字取值.赋值:lable1.Text 2.Te ...

  3. jq判断上下滚动

    $(document).ready(function(){ var p=0,t=0; $(window).scroll(function(e){ p = $(this).scrollTop(); if ...

  4. Win10 1803更新UWP无法安装的解决办法|错误代码0x80073D0D

    升级Win10 1803后,出现了之前安装的UWP.应用无法更新,再此安装失败的现象. 应用商店错误代码为:0x80073D0D,尝试卸载重装商店,清除应用缓存也无法解决. 最终解决办法: 下载Eve ...

  5. vue热重载

    依据官网使用 webpack 的 Hot Module Replacement API,Vuex 支持在开发过程中热重载 mutation.module.action 和 getter.你也可以在 B ...

  6. 观锁和乐观锁——《POJOs in Action》

    1        事务隔离 事务隔离是数据库提供的功能. SQL Server通过SET TRANSACTION ISOLATION LEVEL语句设置事务隔离级别: SET TRANSACTION ...

  7. docker 入门学习

    一 : docker 安装(linux-centos7) 安装docker要求 1.docker只支持在64位cup架构计算机上运行,目前不支持32位cup. 2.建议系统的linux内核版本在3.1 ...

  8. maven release插件将一版本发布到仓库中时Return code is: 401, ReasonPhrase:Unauthorized

    需要在maven的setting.xml中配置servers.server节点,其值为nexus的对应的repository的id以及用户名及密码 <servers> <server ...

  9. git 支持tree命令

    由于git 里面是不支持tree命令的 有两种方法可以达到tree的效果 1.使用 winpty tree.com 2.安装tree.exe可执行文件 下载链接: https://sourceforg ...

  10. vue列表排序实现中的this问题

    最近在看vue框架的知识,然后其中有个例子中的this的写法让我很疑惑 <!DOCTYPE html> <html> <head> <meta charset ...