[BZOJ 1012][JSOI2008]最大数maxnumber(线段树)
Description
现在请求你维护一个数列,要求提供以下两种操作:1、 查询操作。语法:Q L 功能:查询当前数列中末尾L
个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加
上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
数。
Solution
一开始把空的地方都建出来,记一下当前的序列长度,然后就可以进行普通的线段树操作了
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #define Max(a,b) (a>b?a:b) #define MAXN 200005 using namespace std; int m,tot=0; long long d,last=0; struct Node{ int l,r; long long maxn; }t[MAXN*4]; void build(int idx,int l,int r) { t[idx].l=l,t[idx].r=r; if(l==r)return; int mid=(l+r)>>1; build(idx<<1,l,mid); build(idx<<1|1,mid+1,r); } void add(int idx,int a,long long b) { if(t[idx].l==t[idx].r) {t[idx].maxn=b;return;} int mid=(t[idx].l+t[idx].r)>>1; if(a<=mid)add(idx<<1,a,b); else add(idx<<1|1,a,b); t[idx].maxn=Max(t[idx<<1].maxn,t[idx<<1|1].maxn); } long long query(int idx,int a,int b) { if(t[idx].l>=a&&t[idx].r<=b) return t[idx].maxn; int mid=(t[idx].l+t[idx].r)>>1; if(b<=mid)return query(idx<<1,a,b); else if(a>mid)return query(idx<<1|1,a,b); else return Max(query(idx<<1,a,b),query(idx<<1|1,a,b)); } int main() { scanf("%d%lld",&m,&d); build(1,1,m); for(int i=1;i<=m;i++) { char opt; int x;long long t; opt=getchar(); while(opt!='Q'&&opt!='A') opt=getchar(); scanf("%d",&x); if(opt=='Q') { last=query(1,tot-x+1,tot); printf("%lld\n",last); } else if(opt=='A') { t=(last+x)%d; add(1,tot+1,t); tot++; } } return 0; }