bzoj1012 [JSOI2008]最大数maxnumber

1012: [JSOI2008]最大数maxnumber

Time Limit: 3 Sec  Memory Limit: 162 MB
Submit: 5144  Solved: 2308

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

 题意:不解释

分析:简单无聊

因为求最大值时永远只求最后几个的最大值,

所以如果 i < j,    A[i] < A[j] ,那么显然 A[i]是没有用的,因为最大值不可能是A[i](因为存在A[j] > A[i]),

所以我们只用把类似A[i]这样的无用点去除,对这个数列保留一个单调递减的队列,就可以了

增添操作时维护一下单调队列的单调性

 

综上所述,本题得解

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <deque>
 6 #include <vector>
 7 #include <queue>
 8 #include <iostream>
 9 #include <algorithm>
10 #include <map>
11 #include <set>
12 #include <ctime>
13 using namespace std;
14 typedef long long LL;
15 typedef double DB;
16 #define For(i, s, t) for(int i = (s); i <= (t); i++)
17 #define Ford(i, s, t) for(int i = (s); i >= (t); i--)
18 #define MIT (2147483647)
19 #define INF (1000000001)
20 #define MLL (1000000000000000001LL)
21 #define sz(x) ((int) (x).size())
22 #define clr(x, y) memset(x, y, sizeof(x))
23 #define puf push_front
24 #define pub push_back
25 #define pof pop_front
26 #define pob pop_back
27 #define ft first
28 #define sd second
29 #define mk make_pair
30 inline void SetIO(string Name) {
31     string Input = Name+".in",
32     Output = Name+".out";
33     freopen(Input.c_str(), "r", stdin),
34     freopen(Output.c_str(), "w", stdout);
35 }
36 
37 const int N = 200010;
38 typedef pair<int, int> II;
39 int m, Mod;
40 int n, S;
41 II Que[N];
42 
43 inline void Input() {
44     scanf("%d%d", &m, &Mod);
45 }
46 
47 inline void Add(int x) {
48     while(S) {
49         if(Que[S].ft > x) break;
50         S--;
51     }
52     Que[++S] = II(x, ++n);
53 }
54 
55 inline int Ask(int x) {
56     int Left = 1, Right = S, Mid, Ret;
57     while(Left <= Right) {
58         Mid = (Left+Right)>>1;
59         if(Que[Mid].sd >= x) {
60             Right = Mid-1;
61             Ret = Que[Mid].ft;
62         } else Left = Mid+1;
63     }
64     
65     return Ret;
66 }
67 
68 inline void Solve() {
69     int LastAns = 0;
70     while(m--) {
71         char Ch = ' ';
72         int x;
73         while(Ch != 'A' && Ch != 'Q') Ch = getchar();
74         scanf("%d", &x);
75         
76         if(Ch == 'A') Add((LastAns+x)%Mod);
77         else {
78             LastAns = Ask(n-x+1);
79             printf("%d\n", LastAns);
80         }
81     }
82 }
83 
84 int main() {
85     SetIO("1012");
86     Input();
87     Solve();
88     return 0;
89 }
View Code

 

PS:当然,这题也可以用分块、线段树等等数据结构做,但吃力不讨好

 
posted @ 2015-06-22 16:06  yanzx6  阅读(194)  评论(0编辑  收藏  举报