当前位置: 代码迷 >> 综合 >> bzoj1012-(线段树)
  详细解决方案

bzoj1012-(线段树)

热度:4   发布时间:2024-01-12 15:47:20.0

现在请求你维护一个数列,要求提供以下两种操作: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

代码:

#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<queue>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
#define M 200005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
ll d,t,len,n,x;
ll tree[M<<2];
int a[M];
void pushup(int rt)
{tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}
void update(int pos,ll v,int l,int r,int rt)
{if(l==r){tree[rt]=v;return ;}int m=(l+r)>>1;if(pos<=m) update(pos,v,lson);else update(pos,v,rson);pushup(rt);
}
ll query(int ql,int qr,int l,int r,int rt)
{if(ql<=l&&qr>=r){return tree[rt];}int m=(l+r)>>1;ll ret=-1000000000;if(ql<=m) ret=max(ret,query(ql,qr,lson));if(qr>m) ret=max(ret,query(ql,qr,rson));return ret;
}
int main()
{int i,num;char ch;scanf("%d%lld",&num,&d);for(int cas=1;cas<=num;cas++){getchar();ch=getchar();scanf("%lld",&x);len++;if(ch=='Q'){int l=a[n-x+1];int r=a[n];t=query(l,r,1,num,1);printf("%lld\n",t);}else{x=(x%d+t%d)%d;n++;a[n]=len;update(len,x,1,num,1);}}return 0;
}