• 题目描述

    现在请求你维护一个数列,要求提供以下两种操作:

  1. 查询操作。
  • 语法:Q L

    功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。

    限制:L不超过当前数列的长度。(L>=0)

  1. 插入操作。
  • 语法:A n

    • 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查 询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插 入到数列的末尾。

    • 限制:n是整数(可能为负数)并且在长整范围内。

    • 注意:初始时数列是空的,没有一个数。

  • 输入输出格式

  1. 输入格式:

    第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0<D<2,000,000,000)

接下来的M行,每行一个字符串,描述一个具体的操作。语法如上文所述。

  1. 输出格式:

    对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。
  • 输入输出样例
  1. 输入样例#1:

5 100

A 96

Q 1

A 97

Q 1

Q 2

  1. 输出样例#1:

96

93

96


  • 前言:

    本蒟蒻很早以前就在做这道题了,当时是在搞线段树时搜到了这道题,第一眼看到这题我根本不觉得它与线段树有什么关系,于是就随便写了一个二分+伪单调栈,结果连样例都过不了。。。最近又搞起了线段树,先是看了一下黄学长的博客知道自己之前的单调栈错在了哪里,然后又搞了一棵线段树,结果玄学般全部MLE???为什么最近做题总会遇到玄学错误,于是学习黄学长方法,搞个数组记录l和r就过了。


  • 单调栈超级详解:

    推荐先搞懂这道题的手写队列方法:滑动窗口

    我们搞一个数组记录加的每一个数。在我看来,这个数组其实不能叫做栈,另一篇题解这里可能有点表达不太准确(个人观点),然后我们再搞一个数组,我们可以理解为将这个数组储存一个指针,这才是一个单调栈,因为它记录的元素从左到右是依次递减的。我们搞一个tail记录栈顶位置,当一个新数加进来时,我们将它与栈顶的元素做比较,如果栈顶的元素都比他小,就不断tail--,知道删去所有指针或找到一个比它更大的数,则停止操作,将tail++的地方存放这个新数的位置(指针)。大家可以想一想,它是要从后往前找最大的数,如果在后面已经有了一个比前面都大的数,那前面记录的指针都可以不要了,因为从这个数倒数所有查询的答案都是它。

    然后就是查询了,查询我们用二分查找查到我们要的位置,有人若是认真研究了我的代码会发现这个二分查找其实就是个lower_bound,返回大于等于这个数的第一个位置,所以它返回的就是我们需要的下标。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#define ll long long
using namespace std;
const int maxn=200010;
ll sta[maxn];
ll m,d,t=0;
int node[maxn],len=0,tail=0;
int binary_search(int x){
int l=1,r=tail;
int mid;
while(l<=r){
mid=(l+r)>>1;
if(node[mid]>x)r=mid-1;
else if(node[mid]==x)return mid;
else l=mid+1;
}
}
int main()
{
char opt[15];
freopen("bzoj_1012.in","r",stdin);
freopen("bzoj_1012.out","w",stdout);
cin>>m>>d;
while(m--){
scanf("%s",opt);
if(opt[0]=='A'){
ll x;
scanf("%lld",&x);
x=(x+t)%d;
sta[++len]=x;
while(tail&&sta[node[tail]]<=x)tail--;
node[++tail]=len;
}
else{
int l;
scanf("%d",&l);
if(l==0){
cout<<0<<endl;
t=0;
continue;
}
int x=binary_search(len+1-l);
cout<<sta[node[x]]<<endl;
t=sta[node[x]];
}
}
fclose(stdin);
fclose(stdout);
return 0;
}

  • 线段树做fa

    有人说线段树跑得很慢,为什么我这里跑得比单调栈还快???难道因为是黄 学长的玄学技巧??

    我也搞不懂之前的代码为何全部玄学MLE,就当这种新方法一种技巧吧。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=200000;
ll maxx[maxn<<2];
int cnt=0;
int L,R,tar;
ll m,d,t=0;
int le[maxn<<2],ri[maxn<<2];
void build(int now,int l,int r)
{
le[now]=l,ri[now]=r;
if(l==r){
return ;
} int mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
return ;
}
ll query(int now){
int l=le[now],r=ri[now];
if(L<=l&&r<=R){
return maxx[now];
}
int mid=(l+r)>>1;
ll ans=0;
if(L<=mid)ans=max(ans,query(now<<1));
if(R>mid)ans=max(ans,query(now<<1|1));
return ans;
}
void insert(int now,ll x)
{
int l=le[now],r=ri[now];
if(l==r){
maxx[now]=x;
return ;
} int mid=(l+r)>>1;
if(tar<=mid)insert(now<<1,x);
if(mid<tar)insert(now<<1|1,x);
maxx[now]=max(maxx[now<<1],maxx[now<<1|1]);
return ;
}
int main()
{
char opt[15];
cin>>m>>d;
build(1,1,m);
while(m--)
{
scanf("%s",opt);
if(opt[0]=='A'){
ll x;
scanf("%lld",&x);
tar=++cnt;
insert(1,(x+t)%d);
}
else{
int l;
scanf("%d",&l);
if(l!=0)
{
L=cnt-l+1,R=cnt;
t=query(1);
}
else t=0;
cout<<t<<endl;
}
}
return 0;
}

【题解】JSOI2008 最大数的更多相关文章

  1. 【题解】[JSOI2008]最大数

    [题解][P1198 JSOI2008]最大数 正难则反,意想不到. 这道题是动态让你维护一个数列,已经在数列里面的数据不做改变,每次在最后加上一个数,强制在线. 既然正着做很难,考虑如果时间倒流,不 ...

  2. 洛谷P1198 [JSOI2008]最大数

    P1198 [JSOI2008]最大数 267通过 1.2K提交 题目提供者该用户不存在 标签线段树各省省选 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 WA80的戳这QwQ BZOJ都 ...

  3. [JSOI2008]最大数maxnumber

    [JSOI2008]最大数maxnumber 标签: 线段树 单独队列 题目链接 题解 线段树裸题. 如果一直RE可能是你用的cin/cout. Code #include<cstdio> ...

  4. 洛谷 P1198 [JSOI2008]最大数

    洛谷 P1198 [JSOI2008]最大数 题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. ...

  5. BZOJ 1012: [JSOI2008]最大数maxnumber 单调队列/线段树/树状数组/乱搞

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 4750  Solved: 2145[Submi ...

  6. bzoj1012: [JSOI2008]最大数maxnumber(貌似是道线段树喔)

    1012: [JSOI2008]最大数maxnumber 题目:传送门 题解: 发现自己空了一道水题... 1~210000建线段树,其实就是一道裸题... 单点修改+区间查询...1A~ 代码: # ...

  7. P1198 [JSOI2008]最大数(线段树基础)

    P1198 [JSOI2008]最大数 题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制: ...

  8. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

  9. BZOJ-1012[JSOI2008]最大数maxnumber 线段树区间最值

    这道题相对简单下面是题目: 1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec Memory Limit: 162 MB Submit: 6542 Solve ...

  10. 【bzoj1012】[JSOI2008]最大数maxnumber

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8339  Solved: 3624[Submi ...

随机推荐

  1. vga转HDMI与hdmi转VGA区别

  2. python —— 文本特征提取 CountVectorize

    CountVectorize 来自:python学习 文本特征提取(二) CountVectorizer TfidfVectorizer 中文处理 - CSDN博客 https://blog.csdn ...

  3. redis2. sds 字符串(SimpleDynamicString)

    1.标准strcat 会有溢出风险,sdscat无溢出风险 2.空间预分配,惰性空间释放 空间预分配:sds分配空间时,如果原来是5,free是0, sdscat追加一个10长度的,此时字符串加长到1 ...

  4. Springboot整合 mybatis-generator

    1.pom.xml文件中 生成依赖 <plugin> <groupId>org.mybatis.generator</groupId> <artifactId ...

  5. SQL:目录

    ylbtech-SQL:目录 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   作者:ylbtech出处:http://ylbtech.c ...

  6. JVM学习笔记之JDK、JRE、JVM的关系(二)

    JDK(Java Development Kit)是针对Java开发员的产品,是整个Java的核心,包括了Java运行环境JRE.Java工具和Java基础类库.Java Runtime Enviro ...

  7. NLP基础

    1  自然语言处理三大特征抽取器(CNN/RNN/TF)比较 白衣骑士Transformer:盖世英雄站上舞台 华山论剑:三大特征抽取器比较 综合排名情况 以上介绍内容是从几个不同角度来对RNN/CN ...

  8. Docker知识点总结

    一. docker介绍: 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不 ...

  9. Pandas导入导出&pickle文件模块

    Pandas可以读取与存储的文件格式有很多 像csv,excel,json,html等,详细请看官方文档https://pandas.pydata.org/pandas-docs/stable/use ...

  10. NumSharp的数组切片功能

    NumSharp的数组切片功能 原文地址:https://medium.com/scisharp/slicing-in-numsharp-e56c46826630 翻译初稿(英文水平有限,请多包涵): ...