BZOJ 2653: middle(主席树+二分答案)
解题思路
首先可以想到一种暴力做法,就是询问时二分,然后大于等于这个值的设为1,否则设为-1,然后就和GSS1那样统计答案。但是发现这样时间空间复杂度都很爆炸,所以考虑预处理,可以用主席树来做了。以\(rt[i]\)为根线段树维护二分的答案为\(i\)的线段树,线段树下标是位置。处理的时候就排一遍序,然后每次\(mid+1\)的时候发现只有\(mid\)这个位置的值要变成\(-1\),所以可以直接处理。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=20005;
const int M=N*20;
template<class T> void rd(T &x){
x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
}
inline int qmax(int x,int y){return x>y?x:y;}
int n,m,a[N],id[N],lx[M],rx[M],sum[M],ls[M],rs[M],tot,rt[N];
int q[10];
inline bool cmp(int x,int y){return a[x]<a[y];}
void build(int &x,int l,int r){
x=++tot;int mid=(l+r)>>1;
if(l==r) {sum[x]=lx[x]=rx[x]=1;return ;}
build(ls[x],l,mid);build(rs[x],mid+1,r);
sum[x]=sum[ls[x]]+sum[rs[x]];
lx[x]=rx[x]=sum[x];
}
void update(int pre,int &x,int l,int r,int k){
x=++tot;sum[x]=sum[pre];rx[x]=rx[pre];
ls[x]=ls[pre];rs[x]=rs[pre];lx[x]=lx[pre];
if(l==r) {lx[x]=rx[x]=sum[x]=-1;return ;}
int mid=(l+r)>>1;
if(k<=mid) update(ls[pre],ls[x],l,mid,k);
else update(rs[pre],rs[x],mid+1,r,k);
sum[x]=sum[ls[x]]+sum[rs[x]];
lx[x]=qmax(lx[ls[x]],sum[ls[x]]+lx[rs[x]]);
rx[x]=qmax(rx[rs[x]],sum[rs[x]]+rx[ls[x]]);
}
int query_sum(int x,int l,int r,int L,int R){
if(L>R) return 0;
if(L<=l && r<=R) return sum[x];
int mid=(l+r)>>1,ret=0;
if(L<=mid) ret+=query_sum(ls[x],l,mid,L,R);
if(mid<R) ret+=query_sum(rs[x],mid+1,r,L,R);
return ret;
}
int query_lx(int x,int l,int r,int L,int R){
if(L<=l && r<=R) return lx[x];
int mid=(l+r)>>1;
if(L>mid) return query_lx(rs[x],mid+1,r,L,R);
else if(mid>=R) return query_lx(ls[x],l,mid,L,R);
else return qmax(query_lx(ls[x],l,mid,L,R),query_sum(ls[x],l,mid,L,R)+query_lx(rs[x],mid+1,r,L,R));
}
int query_rx(int x,int l,int r,int L,int R){
if(L<=l && r<=R) return rx[x];
int mid=(l+r)>>1;
if(L>mid) return query_rx(rs[x],mid+1,r,L,R);
else if(mid>=R) return query_rx(ls[x],l,mid,L,R);
else return qmax(query_rx(rs[x],mid+1,r,L,R),query_sum(rs[x],mid+1,r,L,R)+query_rx(ls[x],l,mid,L,R));
}
inline bool check(int lim){
int ret=0;
ret+=query_sum(rt[lim],1,n,q[2]+1,q[3]-1);
ret+=query_lx(rt[lim],1,n,q[3],q[4]);
ret+=query_rx(rt[lim],1,n,q[1],q[2]);
return ret>=0?1:0;
}
int main(){
rd(n);int lstans=0;
for(int i=1;i<=n;i++) rd(a[i]),id[i]=i;
sort(id+1,id+1+n,cmp);build(rt[1],1,n);sort(a+1,a+1+n);
for(int i=2;i<=n+1;i++) update(rt[i-1],rt[i],1,n,id[i-1]);
for(rd(m);m;m--){
rd(q[1]);rd(q[2]);rd(q[3]);rd(q[4]);
q[1]=(q[1]+lstans)%n+1;q[2]=(q[2]+lstans)%n+1;
q[3]=(q[3]+lstans)%n+1;q[4]=(q[4]+lstans)%n+1;
sort(q+1,q+1+4);int L=1,R=n,mid;
while(L<=R){
mid=(L+R)>>1;
if(check(mid)) lstans=mid,L=mid+1;
else R=mid-1;
}
printf("%d\n",a[lstans]);lstans=a[lstans];
}
return 0;
}
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 主席树 二分
https://www.lydsy.com/JudgeOnline/problem.php?id=2653 因为是两个方向向外延伸所以不能对编号取前缀和(这里只有前缀和向后传递的性质,不是实际意义的和 ...
- 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 ...
- bzoj 2653 middle(主席树)
题面:https://vjudge.net/problem/HYSBZ-2653 博客:https://blog.csdn.net/litble/article/details/78984846 这个 ...
- BZOJ 1926: [Sdoi2010]粟粟的书架(主席树,二分答案)
BZOJ 1926: [Sdoi2010]粟粟的书架(主席树,二分答案) 题意 : 给你一个长为\(R\)宽为\(C\)的矩阵,第\(i\)行\(j\)列的数为\(P_{i,j}\). 有\(m\)次 ...
- 【bzoj2653】【middle】【主席树+二分答案】
Description 一个长度为 n 的序列 a ,设其排过序之后为 b ,其中位数定义为 b[n/2] ,其中 a,b 从 0 开始标号 , 除法取下整. 给你一个长度为 n 的序列 s .回答 ...
- BZOJ 4556 [Tjoi2016&Heoi2016]字符串 ——后缀数组 ST表 主席树 二分答案
Solution 1: 后缀数组暴力大法好 #include <map> #include <cmath> #include <queue> #include &l ...
- [BZOJ2653]middle 主席树+二分
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2042 Solved: 1123[Submit][Status][Disc ...
随机推荐
- 容器————vector
目录 一.介绍 二.声明及初始化 三.方法 front find remove erase substr 一.介绍 向量 vector 是一种对象实体, 能够容纳许多其他类型相同的元素, 因此又被称为 ...
- [CSP-S模拟测试]:english(可持久化Trie+启发式合并)
题目传送门(内部题24) 输入格式 第一行有$3$个整数$n,opt$,$opt$的意义将在输出格式中提到.第二行有$n$个整数,第$i$个整数表示$a_i$. 输出格式 若$opt=1$,输出一行一 ...
- Java操作Redis小案例
1.下载jar包. http://download.csdn.net/detail/u011637069/9594840包含本案例全部代码和完整jar包. 2.连接到redis服务. package ...
- 测开之路五十七:实现runner和测试报告
准备测试用例 from fox.case import Casefrom src import Calculator class TestCalculator(Case): def setUp(sel ...
- Python笔记(十)_迭代器与生成器
迭代 用for...in来遍历一个可迭代对象的过程就叫迭代 可迭代对象:列表.元组.字典.集合.字符串.生成器 可以使用内置函数isinstance()判断一个对象是否是可迭代对象 >>& ...
- maven导出工程pom文件中依赖的jar包
在工程的pom文件里加上下面plugin, 然后执行mvn clean package -Dmaven.test.skip=true命令,就可以lib包收集起来了 <plugin> < ...
- Boosting Ensemble and GBDT Algorithm
Boosting Ensemble: 机器学习中,Ensemble model除了Bagging以外,更常用的是Boosting.与Bagging不同,Boosting中各个模型是串行的.其思想是,后 ...
- lerna----一个强大的专注组件库的管理工具
最近在看关于lerna的资料,没有中文版api.简书上有一篇文章半英半汉,可以撸来看看. http://www.jianshu.com/p/63ec67445b0f
- u盘在电脑读不出来,但别的可以读
其实一般这种问题都是驱动程序问题导致的,解决方法很简单,不管是win7还是win10都适用: 插入u盘然后在设备管理里删掉设备重新插拔试试. 详细步骤是: 插上U盘 打开设备管理器 ...
- flink-training-course
目录 flink-training-course 大数据领域顶级盛会 Flink Forward Asia 2019 详情