[JSOI2008]最大数maxnumber
题目大意:
现在请求你维护一个数列,要求提供以下两种操作:
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\)行,查询操作或者插入操作。
思路:
强制在线,观察到最多插入\(m\)个数,维护当前数列中的个数\(sum\),则每次查询时检查\([sum-n+1,sum]\)中的最大值即可,插入的话则是单点插入。
算是比较简单的线段树问题。
Code:
#include<stdio.h>
#include<iostream>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mid (l+r)/2
#define debug(x) cout<<#x<<" :"<<x<<endl
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
int t,x,y,z,n,m;
int d;
char s[10];
int pos[maxn],val[maxn];
int q[maxn];
int ans[maxn];
struct node{
int tr[maxn<<2],lazy[maxn<<2];
void pushup(int rt){
tr[rt]=max(tr[rt<<1],tr[rt<<1|1]);
}
void pushdown(int l,int r,int rt){
}
void build(int l,int r,int rt){
if(l==r){
return ;
}
build(lson);
build(rson);
pushup(rt);
}
void update(int L,int R,int l,int r,int rt,int val){
if(L<=l&&r<=R){
tr[rt]=val;
return ;
}
if(L<=mid){
update(L,R,l,mid,rt<<1,val);
}
if(R>mid){
update(L,R,mid+1,r,rt<<1|1,val);
}
pushup(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
return tr[rt];
}
int ans=-0x3f3f3f3f;
if(L<=mid){
ans=max(ans,query(L,R,l,mid,rt<<1));
}
if(R>mid){
ans=max(ans,query(L,R,mid+1,r,rt<<1|1));
}
pushup(rt);
return ans;
}
void init(){
for(int i=1;i<=maxn*4-1;++i){
lazy[i]=0;
}
}
}sgt;
int main(){
while(~scanf("%d %d",&m,&d)){
t=0;
int sum=0;//almost m number
for(int i=1;i<=m;++i){
scanf("%s %d",s,&n);
if(s[0]=='A'){//add a value to the end
n=(n+t)%d;
if(n<0){
n+=d;
n%=d;
}
sum++;
sgt.update(sum,sum,1,m,1,n);
}
else if(s[0]=='Q'){
int ans=sgt.query(sum-n+1,sum,1,m,1);
printf("%d\n",ans);
t=ans;
}
}
}
return 0;
}