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

Sample Output

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;
}

  

posted @ 2017-08-30 10:19  shixinyi  阅读(205)  评论(0编辑  收藏  举报