BZOJ 1012 [JSOI2008]最大数maxnumber (单调栈)
来源:互联网 发布:画梁图软件 编辑:程序博客网 时间:2024/06/05 09:49
1012: [JSOI2008]最大数maxnumber
Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 11124 Solved: 4868
[Submit][Status][Discuss]
Description
现在请求你维护一个数列,要求提供以下两种操作:1、 查询操作。语法:Q L 功能:查询当前数列中末尾L
个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加
上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
数。
Input
第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足D在longint内。接下来
M行,查询操作或者插入操作。
Output
对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。
Sample Input
5 100
A 96
Q 1
A 97
Q 1
Q 2
A 96
Q 1
A 97
Q 1
Q 2
Sample Output
96
93
96
93
96
线段树可以做,RMQ的模板题,新学到一种处理区间问题的思想,单调栈也可以说是单调队列。维护一个栈,栈内元素入栈先后和元素的大小都是有序的,最后取值的时候只需要二分查找最大数的位置,最后输出即可。
由于后入栈的数如果比先入栈的数大的话,先入栈的数不会输出,所以如果后入栈的数大,就让它直接覆盖掉比它小的数中的最大数,栈中此位置储存当前值在原数组中的下标,因为每次询问都是在上一次L的基础上,所以此题可以用单调队列维护。
其实模拟栈的数组储存的就是原数组的下标,数组中代表原数组元素递减排序,这样可以表示当前最大值可以覆盖后面的较小值,二分查找就是在最后一个较大值前面的大数中,查找符合要求的数的下标,最后输出。
想了两天,自己想通了,可还是不怎么会表达,等以后积淀一下再做总结吧。
注意,cin和cout会RE,我交了差不多20次才A到,这就是玄学的奇妙之处吧。
代码实现:
#include<iostream>#include<algorithm>#include<cstring>#include<cmath>#include<queue>#include<cstdio>#define ll long long#define mset(a,x) memset(a,x,sizeof(a))using namespace std;const double PI=acos(-1);const int inf=0x3f3f3f3f;const double esp=1e-6;const int maxn=2e5+5;const int mod=1e9+7;int dir[4][2]={0,1,1,0,0,-1,-1,0};ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}ll lcm(ll a,ll b){return a/gcd(a,b)*b;}ll inv(ll b){if(b==1)return 1; return (mod-mod/b)*inv(mod%b)%mod;}ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;}ll ans[maxn],Stack[maxn]; //Stack单调栈,入栈元素入队先后与数的大小都有序 ,ans储存修改后的值 int main(){char x;int i,j,k,n,d,y,top,len,END; //END储存后L个数中的最大数,top记录当前最大值在栈中的位置,len记录元素个数 while(scanf("%d %d",&n,&d)){mset(ans,0);mset(Stack,0);END=len=top=0;for(i=1;i<=n;i++){getchar();scanf("%c %d",&x,&y);if(x=='A'){y=(y+END)%d; //最大值加上y后取模d ans[++len]=y; //y入队列,下标自加 while(top&&ans[Stack[top]]<=y) //栈不为空,倒序排序 top--; Stack[++top]=len; //到当前栈中这个元素对应的原数组的下标 }else{int temp=lower_bound(Stack+1,Stack+top+1,len-y+1)-Stack; //找到最大值下标的位置 END=ans[Stack[temp]]; //输出并记录后L个数的最大值 printf("%d\n",END); }}}return 0;}
阅读全文
0 0
- bzoj 1012: [JSOI2008]最大数maxnumber(单调栈+二分)
- BZOJ 1012 [JSOI2008]最大数maxnumber (单调栈)
- BZOJ 1012: [JSOI2008]最大数maxnumber 单调栈
- [BZOJ 1012][JSOI2008]最大数maxnumber:线段树|单调栈
- BZOJ 1012([JSOI2008]最大数maxnumber-单调队列)
- 【BZOJ 1012】 [JSOI2008]最大数maxnumber(单调队列做法)
- BZOJ 1012: [JSOI2008]最大数maxnumber 单调队列/线段树
- BZOJ 1012 JSOI2008 最大数maxnumber 单调栈+二分 / 线段树
- BZOJ 1012[jsoi2008] 最大数maxnumber 线段树(或者是单调队列+二分)
- 【单调栈】Bzoj 1012: 最大数maxnumber
- 【单调队列】1012: [JSOI2008]最大数maxnumber
- [JSOI2008] [BZOJ1012] 最大数maxnumber - 单调栈
- [BZOJ1012][JSOI2008]最大数maxnumber-单调栈
- [BZOJ]1012 [JSOI2008]最大数maxnumber (线段树维护区间最值 || 单调栈+二分查找)
- 1012: [JSOI2008]最大数maxnumber 单调栈+二分
- BZOJ1012: [JSOI2008]最大数maxnumber(单调栈)
- BZOJ 1012-最大数maxnumber(单调栈)
- BZOJ 1012: [JSOI2008]最大数maxnumber
- 有关垂直同步的理解和是否开启
- 继承与组合的优缺点
- 第二周第二节课
- matlab图像处理
- MySQL建库建表
- BZOJ 1012 [JSOI2008]最大数maxnumber (单调栈)
- ceph 副本数据的写入位置和读出
- 读书笔记
- 获取当前DLL所在路径
- 通过args数组获取数据
- Android ListView 之 Item 定位显示
- Ubuntu16.04 TLS 安装mentohust连接校园网
- 两个变量交换值
- 【element-ui】messageBox弹窗提示消息换行问题。