• 题目描述

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

  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. 黑马vue---20、v-if和v-show的使用和特点

    黑马vue---20.v-if和v-show的使用和特点 一.总结 一句话总结: v-if 的特点:每次都会重新删除或创建元素 v-show 的特点: 每次不会重新进行DOM的删除和创建操作,只是切换 ...

  2. POJ 2109 -- Power of Cryptography

    Power of Cryptography Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 26622   Accepted: ...

  3. 【8583】ISO8583各域段的说明

    [ISO8583各域段的说明] 1,信息类型(message type)定义位图位置:-格式:定长类型:N4描述:数据包的第一部分,定义数据包的类型.数据类型由数据包的发起者设定,应遵循以下要求:数据 ...

  4. django中iframe问题

    因为在django中无法识别我们普通的url格式,比如使用<iframe src="articles.html"></iframe>,这种格式django无 ...

  5. 【转】APIJSON,让接口见鬼去吧!

    我: APIJSON,让接口和文档见鬼去吧! https://github.com/TommyLemon/APIJSON 服务端: 什么鬼? 客户端: APIJSON是啥? 我: APIJSON是一种 ...

  6. python 实例方法、类方法和静态方法

    #!/usr/bin/env python3.6 #-*- coding:utf-8 -*- # class Person(object): city = 'Beijing' def __init__ ...

  7. java+目录上传

    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 首先我们需要了解的是上传文件三要素: 1.表单提交方式:post (get方式提交有大小 ...

  8. elk报错解决

    .elasticsearch启动失败如下: [root@bogon home]# /home/elasticsearch-/bin/elasticsearch [--11T07::,][WARN ][ ...

  9. Base64加密 解密

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  10. 如何查看linux系统安装时间

    第一种方法: 先查看系统盘挂到哪个分区上,然后用 dumpe2fs  查看这个磁盘分区 创建的时间,即可查出此 服务器 系统安装的时间.() # dumpe2fs /dev/sda3|grep -i ...