洛谷 P1198 [JSOI2008]最大数
题目描述
现在请求你维护一个数列,要求提供以下两种操作:
1、 查询操作。
语法:Q L
功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。
限制:L不超过当前数列的长度。
2、 插入操作。
语法:A n
功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。
限制:n是整数(可能为负数)并且在长整范围内。
注意:初始时数列是空的,没有一个数。
输入输出格式
输入格式:
第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0<D<2,000,000,000)
接下来的M行,每行一个字符串,描述一个具体的操作。语法如上文所述。
输出格式:
对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。
输入输出样例
输入样例#1:
5 100 A 96 Q 1 A 97 Q 1 Q 2
输出样例#1:
96 93 96
说明
单调栈
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define MAXN 200000+15 using namespace std; long long M,D,ask,t,len,top,a[MAXN],num[MAXN]; //a数组表示栈储存的数的编号,num数组存储数列; char b; int main(){ cin>>M>>D;//M个操作,mod值为D; for(int i=1;i<=M;i++){ cin>>b>>ask; if(b=='A'){//如果为插入操作; ask=(ask+t)%D;//按题目要求将n加上t并%D num[++len]=ask;//将元素插到数列的最后 while(top&&num[a[top]]<=ask)//栈中有元素,维护一个单调递减的栈 top--; a[++top]=len; } /* 维护一个递减栈的原因: 考虑两个是ai和aj,如果i>j,并且ai>aj的话, 那么我们可以发现j没有任何存在的意义了。 因为如果aj可以作为最终答案的话,一定就会经过ai。 然后就不可能选aj了。 */ else{ int y=lower_bound(a+1,a+top+1,len-ask+1)-a;//二分答案 t=num[a[y]]; cout<<t<<endl; } } return 0; }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。