[JSOI2008]最大数

题目描述

现在请求你维护一个数列,要求提供以下两种操作:

1、 查询操作。

语法:Q L

功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。

限制:L不超过当前数列的长度。

2、 插入操作。

语法:A n

功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。

限制:n是整数(可能为负数)并且在长整范围内。

注意:初始时数列是空的,没有一个数。

输入输出格式

输入格式:

第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0<D<2,000,000,000)

接下来的M行,每行一个字符串,描述一个具体的操作。语法如上文所述。

输出格式:

对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。

输入输出样例

输入样例#1:
5 100
A 96
Q 1
A 97
Q 1
Q 2
输出样例#1:
96
93
96

题解:

运用线段树的算法。

这道题看似长度是变化的,其实可以转化

直接将序列看做1~m的数列,将数一个一个加入,并记录当前位置就行了

首先建树,把所有的节点的值赋成min_int。用[i,j]表示该区间的最大值。

1)读入Q L操作。用len表示区间的大小,在len+1的位置放入(L+T)%D的值。

2)读入A n操作。输出区间[len-n+1,len]这个区间中的最大值,并把t的值进行更新。

此题还可以用二分和单调栈

 

 1 #include<iostream>  
 2 #include<cstring>  
 3 #include<cstdio>   
 4 using namespace std;  
 5 int M,D,t=0; 
 6 int size;  
 7 int a[200500];  
 8 int num[200500];  
 9 int main()  
10 {  
11     int Ln,len=0;  
12     char QA[5];  
13     scanf("%d%d", &M, &D);  
14     while(M--)  
15     {  
16         scanf("%s %d", QA, &Ln); 
17         if(QA[0] == 'A')//查询操作 
18         {  
19             Ln=(Ln+t)%D;  
20             num[++len]=Ln;//每次加入一个Ln,num数组长度++ 
21             while(size&&num[a[size]]<=Ln) 
22                 size--;//单调栈操作 
23             a[++size]=len;  
24         }  
25         else //插入操作 
26         {  
27             int pos=lower_bound(a+1,a+size+1,len-Ln+1)-a; //二分查找 
28             t=num[a[pos]]; 
29             cout<<t<<endl;  
30         }  
31     }  
32     return 0;  
33 }

 

线段树

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 int c[800001],ans;
 6 void add(int rt,int l,int r,int p,int k)
 7 {
 8     if (l==r)
 9     {
10         c[rt]=k;
11         return;
12     }
13     int mid=(l+r)>>1;
14     if (p<=mid) add(rt<<1,l,mid,p,k);
15     else add(rt<<1|1,mid+1,r,p,k);
16     c[rt]=max(c[rt<<1],c[rt<<1|1]);
17 }
18 int query(int rt,int l,int r,int L,int R)
19 {
20     if (l>=L&&r<=R)
21     {
22         return c[rt];
23     }
24     int mid=(l+r)>>1,s=-2147283647;
25     if (L<=mid) s=max(s,query(rt<<1,l,mid,L,R));
26     if (R>mid) s=max(s,query(rt<<1|1,mid+1,r,L,R));
27 return s;
28 }
29 void build(int rt,int l,int r)
30 {
31     c[rt]=-2147283647;
32     if (l==r)return;
33     int mid=(l+r)>>1;
34     build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
35 }
36 int main()
37 {int n;
38 char ch;
39 int m,d,t,i,l;
40     cin>>m>>d;
41     t=0;
42     int x=0;
43     build(1,1,m);
44     for (i=1;i<=m;i++)
45     {
46         cin>>ch;
47         if (ch=='A')
48          {
49              scanf("%d",&n);
50              n=(n+t)%d;
51              x++;
52              add(1,1,m,x,n);
53          }
54          else 
55          {
56              scanf("%d",&l);
57              ans=query(1,1,m,x-l+1,x);
58              t=ans;
59              printf("%d\n",ans);
60          }
61     }
62 }
posted @ 2017-07-05 17:28  Z-Y-Y-S  阅读(207)  评论(0编辑  收藏  举报