现在请求你维护一个数列,要求提供以下两种操作:1、 查询操作。语法:Q L 功能:查询当前数列中末尾L
个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加
上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
数。
现在请求你维护一个数列,要求提供以下两种操作:1、 查询操作。语法:Q L 功能:查询当前数列中末尾L
个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加
上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
数。
第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足D在longint内。接下来
M行,查询操作或者插入操作。
对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。
#include<iostream>
#include<fstream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<deque>
#include<utility>
#include<map>
#include<set>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<functional>
#include<sstream>
#include<cstring>
#include<bitset>
#include<stack>
using namespace std;
int m,d,num,len,t,ll;
char aq[2];
int lef[1000005],rig[1000005],data[1000005];
void build(int root,int l,int r)
{
lef[root]=l;
rig[root]=r;
if(l==r)return ;
int mid=(l+r)/2;
build(root*2,l,mid);
build(root*2+1,mid+1,r);
}
void modify(int root,int x,int y)
{
if(lef[root]==rig[root])
{
data[root]=y;
return ;
}
int mid=(lef[root]+rig[root])/2;
if(x<=mid)modify(root*2,x,y); else modify(root*2+1,x,y);
data[root]=max(data[root*2],data[root*2+1]);
}
int query(int root,int l,int r)
{
if(l==lef[root] && r==rig[root])return data[root];
int mid=(lef[root]+rig[root])/2;
if(r<=mid)return query(root*2,l,r);
if(l>mid)return query(root*2+1,l,r);
return max(query(root*2,l,mid),query(root*2+1,mid+1,r));
}
int main()
{
scanf("%d%d",&m,&d);
build(1,1,m);
for(int i=1;i<=m;i++)
{
scanf("%s",aq);
if(aq[0]==‘A‘)
{
scanf("%d",&num);
modify(1,++ll,(t%d+num%d)%d);
}
else
{
scanf("%d",&len);
t=query(1,ll-len+1,ll);
printf("%d\n",t);
}
}
return 0;
}
BZOJ 1012: [JSOI2008]最大数maxnumber(线段树)
原文:http://www.cnblogs.com/winmt/p/6562100.html