现在的位置: 首页 > 综合 > 正文

bzoj1012[JSOI2008]最大数maxnumber

2018年01月13日 ⁄ 综合 ⁄ 共 959字 ⁄ 字号 评论关闭

Description

现在请求你维护一个数列,要求提供以下两种操作: 1、 查询操作。语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。 2、 插入操作。语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个数。

Input

第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0

Output

对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。

Sample Input

5 100

A 96

Q 1

A 97

Q 1

Q 2

Sample Output

96

93

96

斯巴达…………

果真如黄巨大所说,学完splay之后看什么题都变成splay了。

原来想的是用splay支持插入+区间查询,后来发现根本不要那么麻烦。因外每次插入都在末尾,区间查询也只是一段后缀的最大值。感觉单调栈可做……

后来瞄了一眼题解,发现真是单调栈……

学着标程写了一个STL的lower_bound二分,感觉怪怪的

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define maxn 200005
using namespace std;
int n,t,d,s,len,top;
char ch[5];
int a[maxn];
int zhan[maxn];
int main()
{
scanf("%d%d",&n,&d);
for (int i=1;i<=n;i++)
 {
        scanf("%s%d",ch,&s);
  if (ch[0]=='A') 
  {
  s=(t+s)%d;
  a[++len]=s;
  while (top && a[zhan[top]]<=s) top--;
  zhan[++top]=len;
  }else 
  if (ch[0]=='Q')
  {
  int pos = lower_bound(zhan+1,zhan+top+1,len-s+1)-zhan;
printf("%d\n",t=a[zhan[pos]]);  
  }
 }
}

抱歉!评论已关闭.