bzoj1012 最大数maxnumber
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
HINT
数据如下http://pan.baidu.com/s/1i4JxCH3
一个月前写过,记得当时看到这道题,第一反应是 数据结构题吗?第二反应是 哦每次都是在末尾插入,查询也是从某位置到末尾,好简单啊。
然而今天看了半天都没有思路,看自己的代码也不知道自己代码在干什么,真是越学竞赛智商越低。
我们发现,如果存在 i 和 j 满足 i < j 且 a[i] < a[j] ,那么a[i] 对答案一定没有贡献。
那么我们维护一个单调栈,每次查询时二分就可以了。
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; const int maxn=2e5+10; long long M,mod,len=0,ans=0,zz[maxn],n,a[maxn],tot; long long aa,fl;char cc; long long read(){ aa=0;fl=1;cc=getchar(); while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') fl=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); return aa*fl; } long long ef(int l,int r,int pos) { if(l==r) return a[zz[l]]; int mid=(l+r)>>1; if(zz[mid]==pos) return a[zz[mid]]; if(zz[mid]>pos) return ef(l,mid,pos); return ef(mid+1,r,pos); } int main() { M=read();mod=read(); while(M--) { while(cc!='Q'&&cc!='A') cc=getchar(); if(cc=='A') { n=read(); n=(n+ans)%mod; while(len&&a[zz[len]]<=n) len--; zz[++len]=++tot; a[tot]=n; } else { n=read(); ans=ef(1,len,tot-n+1); printf("%lld\n",ans); } } return 0; }
弱者就是会被欺负呀