BZOJ 2653: middle 主席树 二分
https://www.lydsy.com/JudgeOnline/problem.php?id=2653
因为是两个方向向外延伸所以不能对编号取前缀和(这里只有前缀和向后传递的性质,不是实际意义的和),那么对排序后的数字取前缀和,线段树维护编号然后二分就可以了。
在一个值相对的线段树中,数小于该值的位置视为-1,数大于等于该值的位置视为+1. 那么当可取的区间内可以的到的最大的和>=0时该数就是合法的。
维护lmx, rmx, sum三个值分别表示该区间从左向右能得到的最大前缀和、从右向左能得到的最大前缀和、区间和。
二分到区间没有的数也没有关系,二分终究会收敛到区间中存在的数。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int maxn=;
pa a[maxn];
int n,m;
int q[]={};
int rt[maxn]={};
int siz[maxn*]={},lmx[maxn*]={},rmx[maxn*]={},lc[maxn*]={},rc[maxn*]={},tot=;
inline void updata(int x){
siz[x]=siz[lc[x]]+siz[rc[x]];
lmx[x]=max(lmx[lc[x]],siz[lc[x]]+lmx[rc[x]]);
rmx[x]=max(rmx[rc[x]],siz[rc[x]]+rmx[lc[x]]);
}
void build(int &x,int l,int r){
x=++tot; siz[x]=lmx[x]=rmx[x]=(r-l+);
if(l==r)return;
int mid=(l+r)/;
build(lc[x],l,mid);
build(rc[x],mid+,r);
}
void inser(int &x,int y,int l,int r,int z){
x=++tot;siz[x]=siz[y];lmx[x]=lmx[y];rmx[x]=rmx[y];lc[x]=lc[y];rc[x]=rc[y];
if(l==r){siz[x]=-;lmx[x]=;rmx[x]=;return;}
int mid=(l+r)/;
if(z<=mid) inser(lc[x],lc[y],l,mid,z);
else inser(rc[x],rc[y],mid+,r,z);
updata(x);
}
int getsum(int x,int l,int r,int zl,int zr){
if(zl>zr)return ;
if(zl<=l&&r<=zr){return siz[x];}
int mid=(l+r)/,ans=;
if(zl<=mid)ans=getsum(lc[x],l,mid,zl,zr);
if(mid<zr)ans+=getsum(rc[x],mid+,r,zl,zr);
return ans;
}
int getl(int x,int l,int r,int zl,int zr){
if(zl>zr)return ;
if(zl<=l&&r<=zr)return lmx[x];
int mid=(l+r)/,ans=;
if(zl<=mid)ans=getl(lc[x],l,mid,zl,zr);
if(mid<zr)ans=max(ans,getl(rc[x],mid+,r,zl,zr)+getsum(lc[x],l,mid,zl,mid));
return ans;
}
int getr(int x,int l,int r,int zl,int zr){
if(zl>zr)return ;
if(zl<=l&&r<=zr)return rmx[x];
int mid=(l+r)/,ans=;
if(mid<zr)ans=getr(rc[x],mid+,r,zl,zr);
if(zl<=mid)ans=max(ans,getr(lc[x],l,mid,zl,zr)+getsum(rc[x],mid+,r,mid+,zr));
return ans;
}
bool check(int x){
int z=getsum(rt[x],,n,q[],q[]);//cout<<z<<endl;
int w=getl(rt[x],,n,q[]+,q[]);//cout<<w<<endl;
int k=getr(rt[x],,n,q[],q[]-);//cout<<k<<endl;
if(z+w+k>=)return ;
else return ;
}
inline int find(){
int l=,r=n,mid;
while(l<r){
mid=(l+r+)/;
if(check(mid))l=mid;
else r=mid-;
}return l;
}
int main(){
scanf("%d",&n);
int x;
for(int i=;i<=n;i++){ scanf("%d",&x); a[i]=make_pair(x,i); }
sort(a+,a++n);build(rt[],,n);
for(int i=;i<=n;i++){ rt[i]=rt[i-];inser(rt[i],rt[i],,n,a[i-].second); }
int ans=;scanf("%d",&m);
for(int i=;i<=m;i++){
scanf("%d%d%d%d",&q[],&q[],&q[],&q[]);
q[]=(q[]+ans)%n+;q[]=(q[]+ans)%n+;
q[]=(q[]+ans)%n+;q[]=(q[]+ans)%n+;
sort(q,q+);ans=a[find()].first;
printf("%d\n",ans);
}
return ;
}
BZOJ 2653: middle 主席树 二分的更多相关文章
- bzoj 2653: middle (主席树+二分)
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2522 Solved: 1434[Submit][Status][Disc ...
- BZOJ 2653: middle(主席树+二分答案)
传送门 解题思路 首先可以想到一种暴力做法,就是询问时二分,然后大于等于这个值的设为1,否则设为-1,然后就和GSS1那样统计答案.但是发现这样时间空间复杂度都很爆炸,所以考虑预处理,可以用主席树来做 ...
- bzoj 2653 middle(主席树)
题面:https://vjudge.net/problem/HYSBZ-2653 博客:https://blog.csdn.net/litble/article/details/78984846 这个 ...
- BZOJ 2653: middle [主席树 中位数]
传送门 题意: 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右 ...
- BZOJ 2653 middle | 主席树
题目: http://www.lydsy.com/JudgeOnline/problem.php?id=2653 题解: 设答案为ans,把大于等于ans的记为1,小于的记为-1,这样可以知道当前an ...
- [BZOJ2653]middle 主席树+二分
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2042 Solved: 1123[Submit][Status][Disc ...
- [BZOJ 2653] middle(可持久化线段树+二分答案)
[BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...
- BZOJ.1926.[SDOI2010]粟粟的书架(前缀和 主席树 二分)
题目链接 题意: 在给定矩形区域内找出最少的数,满足和>=k.输出数的个数.两种数据范围. 0~50 注意到(真没注意到...)P[i,j]<=1000,我们可以利用前缀和预处理. num ...
- 2018湘潭邀请赛C题(主席树+二分)
题目地址:https://www.icpc.camp/contests/6CP5W4knRaIRgU 比赛的时候知道这题是用主席树+二分,可是当时没有学主席树,就连有模板都不敢套,因为代码实在是太长了 ...
随机推荐
- 2016.6.17——Remove Duplicates from Sorted Array
Remove Duplicates from Sorted Array 本题收获: 1.“删除”数组中元素 2.数组输出 题目: Given a sorted array, remove the du ...
- Linux内存初始化【转】
转自:http://www.cnblogs.com/super-king/p/3291120.html start_kernel -> setup_arch 在这个函数中我们主要看这几个函数. ...
- Linux内核触摸屏驱动--多点触摸 【转】
转自:http://blog.chinaunix.net/uid-24227137-id-3127126.html 简介 为了使用功能强大的多点触控设备,就需要一种方案去上报用户层所需的详细的手指 ...
- mysql insert锁机制【转】
最近再找一些MySQL锁表原因,整理出来一部分sql语句会锁表的,方便查阅,整理的不是很全,都是工作中碰到的,会持续更新 笔者能力有限,如果有不正确的,或者不到位的地方,还请大家指出来,方便你我,方便 ...
- 实现checkebox全选取消操作
方法一: javascript代码: function checkedChild(obj,index){ var checkBoxs = document.getElementsByName(&quo ...
- 读书笔记 effective c++ Item 52 如果你实现了placement new,你也要实现placement delete
1. 调用普通版本的operator new抛出异常会发生什么? Placement new和placement delete不是C++动物园中最常遇到的猛兽,所以你不用担心你对它们不熟悉.当你像下面 ...
- 数据库——mysql如何获取当前时间
1.1 获得当前日期+时间(date + time)函数:now() 除了 now() 函数能获得当前的日期时间外,MySQL 中还有下面的函数: current_timestamp() curren ...
- 如何成为技术大牛——阿里CodeLife
天天写业务代码的程序员,怎么成为技术大牛,开始写技术代码? 几个误区 跟着大牛,就可以成为大牛.首先,大牛时间很宝贵,不可能花很多时间去指导你:其次,简单的模仿大牛,只能学到表面知识,不可能成为大牛: ...
- 如何查看页面是否开启了gzip压缩
1.谷歌浏览器 F12 2.在表头单击鼠标右键 3.如果开启了gzip则显示gzip,没有则是空
- C++之可调用对象
C++中的可调用对象分为以下几种: 函数 函数指针 lambda表达式 bind创建的对象 重载了函数调用运算符(即“()”)的类 函数.函数指针不再介绍.lambda表达式与bind创建的类参考—— ...