BZOJ——1012: [JSOI2008]最大数maxnumber || 洛谷—— P1198 [JSOI2008]最大数

http://www.lydsy.com/JudgeOnline/problem.php?id=1012||

https://www.luogu.org/problem/show?pid=1198

Time Limit: 3 Sec  Memory Limit: 162 MB
Submit: 10824  Solved: 4735
[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如上文中所述,满足D在longint内。接下来
M行,查询操作或者插入操作。

Output

  对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。

Sample Input

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

Sample Output

96
93
96

HINT

 

  数据如下http://pan.baidu.com/s/1i4JxCH3

 

Source

 

①区间查询最值考虑线段树、

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdio>
 4 
 5 using namespace std;
 6 
 7 const int N(200005);
 8 int t,mod,n,x[N],ans;
 9 char ch,s[N];
10 
11 struct Tree
12 {
13     int l,r,sum;
14 }tr[N<<2];
15 #define lc (now<<1)
16 #define rc (now<<1|1)
17 #define mid (tr[now].l+tr[now].r>>1)
18 inline void Tree_up(int now)
19 {
20     tr[now].sum=max(tr[lc].sum,tr[rc].sum);
21 }
22 void Tree_build(int now,int l,int r)
23 {
24     tr[now].l=l; tr[now].r=r;
25     if(l==r) return ;
26     Tree_build(lc,l,mid);
27     Tree_build(rc,mid+1,r);
28 }
29 void Tree_change(int now,int to,int x)
30 {
31     if(tr[now].l==tr[now].r)
32     {
33         tr[now].sum=x;
34         return ;
35     }
36     if(to<=mid) Tree_change(lc,to,x);
37     else Tree_change(rc,to,x);
38     Tree_up(now);
39 }
40 int Tree_query(int now,int l,int r)
41 {
42     if(tr[now].l==l&&r==tr[now].r) return tr[now].sum;
43     if(r<=mid) return Tree_query(lc,l,r);
44     else if(l>mid) return Tree_query(rc,l,r);
45     else return max(Tree_query(lc,l,mid),Tree_query(rc,mid+1,r));
46 }
47 
48 int main()
49 {
50     scanf("%d%d",&t,&mod);
51     for(int i=1;i<=t;i++)
52     {
53         cin>>ch>>x[i]; s[i]=ch;
54         if(ch=='A') n++;
55     }
56     Tree_build(1,1,n);
57     int cnt=0;
58     for(int i=1;i<=t;i++)
59     {
60         if(s[i]=='A')
61             Tree_change(1,++cnt,(ans+x[i])%mod);
62         else
63         {
64             ans=Tree_query(1,cnt-x[i]+1,cnt);
65             printf("%d\n",ans);
66         }
67     }
68     return 0;
69 }
线段树AC

 

②单调递减栈,二分查找位于L处的值

 1 #include <algorithm>
 2 #include <cstdio>
 3 
 4 using namespace std;
 5 
 6 const int N(200005);
 7 int n,mod,ans,x;
 8 int stack[N],top,num[N],len;
 9 
10 int main()
11 {
12     scanf("%d%d",&n,&mod);
13     for(char ch[2];n--;)
14     {
15         scanf("%s%d",ch,&x);
16         if(ch[0]=='A')
17         {
18             x=(x+ans)%mod;
19             num[++len]=x;
20             for(;num[stack[top]]<=x&&stack[top]>0&&top;) top--;
21             stack[++top]=len;
22         }
23         else
24         {
25             int l=1,r=top;
26             for(int mid;l<=r;)
27             {
28                 mid=l+r>>1;
29                 if(stack[mid]<len-x+1) l=mid+1;
30                 else r=mid-1,ans=num[stack[mid]];
31             }
32             printf("%d\n",ans);
33         }
34     }
35     return 0;
36 }
单调栈AC

 

posted @ 2017-08-19 18:30  Aptal丶  阅读(251)  评论(0编辑  收藏  举报