[JSOI2008]最大数maxnumber

1012: [JSOI2008]最大数maxnumber

Time Limit: 3 Sec  Memory Limit: 162 MB
Submit: 5667  Solved: 2461
[Submit][Status][Discuss]

Description

现在请求你维护一个数列,要求提供以下两种操作: 1、 查询操作。语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。 2、 插入操作。语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个数。

Input

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

Output

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

Sample Input

5 100
A 96
Q 1
A 97
Q 1
Q 2

Sample Output

96
93
96

HINT

 

Source

                           [Submit][Status][Discuss]

 
  1.单调队列,比较好理解,就是如果要新加入的数比前面若干个数大,就把这若干个数覆盖掉,通俗点说,又靠后值又大的数比较diao,因为撑死20w个数,所以开两个20w的数组就够了。
  我们平时写单调队列时,貌似比较多的是用两个指针head,tail来维护队列Q[]数组,但这题貌似行不通,因为每次询问的L不固定,不能舍弃数列的任意一部分,所以用了“覆盖”的方法。

  注意:在输入字符A或Q时,如果像我下面那样定义ch[5],用 cin>>ch 是错的,要用scanf("%s",ch); 否则会RE,我也不知道为啥

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 using namespace std;

 5 int Q[200005];

 6 int a[200005];

 7 char ch[5];

 8 int L,N,T,D,M,tot;

 9 inline void workA();

10 inline void workQ();

11 int main(){

12     cin>>M>>D;

13     for(int i=1;i<=M;i++){

14         scanf("%s",ch);

15         //cin>>ch;//RE的 

16         if(ch[0]=='A')

17             workA();

18         else

19             workQ();

20     }

21     return 0;

22 }

23 inline void workA(){

24     scanf("%d",&N);

25     a[++tot]=(T+N)%D;

26     for(int i=tot;i;i--){

27         if(Q[i]<a[tot])

28            Q[i]=a[tot];

29         else break;

30     }

31 }

32 inline void workQ(){

33     scanf("%d",&L);

34     printf("%d\n",T=Q[tot-L+1]);

35 }

  

  2.用线段树,相比之下太长了,还容易错,就不分析了,网上随便整的一个代码

  

 1 #include<iostream>

 2 #include<cstdio>

 3 #define inf 0x7fffffff

 4 using namespace std;

 5 int m,mod,last,cnt;

 6 struct data{int l,r,mx;}t[800005];

 7 void build(int k,int l,int r)

 8 {

 9     t[k].l=l;t[k].r=r;t[k].mx=-inf;

10     if(l==r)return;

11     int mid=(l+r)>>1;

12     build(k<<1,l,mid);

13     build(k<<1|1,mid+1,r);

14 }

15 int ask(int k,int x,int y)

16 {

17     int l=t[k].l,r=t[k].r;

18     if(l==x&&r==y)return t[k].mx;

19     int mid=(l+r)>>1;

20     if(y<=mid)return ask(k<<1,x,y);

21     else if(x>mid)return ask(k<<1|1,x,y);

22     else return max(ask(k<<1,x,mid),ask(k<<1|1,mid+1,y));

23 }

24 void insert(int k,int x,int y)

25 {

26     int l=t[k].l,r=t[k].r;

27     if(l==r){t[k].mx=y;return;}

28     int mid=(l+r)>>1;

29     if(x<=mid)insert(k<<1,x,y);

30     else insert(k<<1|1,x,y);

31     t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);

32 }

33 int main()

34 {

35     scanf("%d%d",&m,&mod);

36     build(1,1,m);

37     for(int i=1;i<=m;i++)

38     {

39         char ch[5];scanf("%s",ch);

40         int x;

41         if(ch[0]=='A')

42         {

43             cnt++;

44             scanf("%d",&x);x=(x+last)%mod;

45             insert(1,cnt,x);

46         }

47         else 

48         {

49             scanf("%d",&x);

50             last=ask(1,cnt-x+1,cnt);

51             printf("%d\n",last);

52         }

53     }

54     return 0;

55 }

 

 

你可能感兴趣的:(number)