BZOJ1012[JSOI2008]最大数maxnumber 题解

题目大意:

  维护一个数列,有两种操作:1、 查询当前数列中末尾L个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、插入操作:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,再将所得答插入到数列的末尾。初始时数列是空的,没有一个数。

思路:

  讲道理这道题用线段树肯定不是最好的(比如用栈更快),但是我现在在学线段树,就拿来练练手。线段树裸题,有单点加入、区间查询操作。

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 using namespace std;
 5 
 6 int da[800001];
 7 
 8 void add(int l,int r,int x,int y,int cur)
 9 {
10     da[cur]=max(da[cur],y);
11     if (l==r) return;
12     int mid=l+r>>1;
13     if (x>mid) add(mid+1,r,x,y,cur<<1|1);
14     else add(l,mid,x,y,cur<<1);
15 }
16 
17 int ask(int L,int R,int l,int r,int cur)
18 {
19     if (L>=l && R<=r) return da[cur];
20     int mid=L+R>>1,ans=0;
21     if (l<=mid) ans=max(ans,ask(L,mid,l,r,cur<<1));
22     if (r>mid) ans=max(ans,ask(mid+1,R,l,r,cur<<1|1));
23     return ans;
24 }
25 
26 int main()
27 {
28     int m,mod,ans=0,n=0;
29     scanf("%d%d",&m,&mod);
30     for (int i=1;i<=m;i++)
31     {
32         int l;
33         char ch=getchar();
34         while (ch<'A' || ch>'Z') ch=getchar();
35         scanf("%d",&l);
36         if (ch=='A')
37         {
38             n++;
39             int x=(l+ans)%mod;
40             add(1,m,n,x,1);
41         }
42         else printf("%d\n",ans=ask(1,m,n-l+1,n,1));
43     }
44     return 0;
45 }

 

我一直在繁华的苍凉中徘徊着,用一颗OI的心寻找着生命和宇宙的美妙与玄奥。
posted @ 2016-08-03 17:14  HHshy  阅读(156)  评论(0编辑  收藏  举报