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
A 96
Q 1
A 97
Q 1
Q 2
Sample Output
96
93
96
93
96
HINT
【分析】
Orz。。。无所不能的树状数组,自己看代码看得懂吧。。。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6 #include <utility> 7 #include <iomanip> 8 #include <string> 9 #include <cmath> 10 #include <map> 11 12 const int MAXN = 200000 + 10; 13 const int MAX = 32000 + 10; 14 using namespace std; 15 typedef long long ll; 16 ll m, MOD, l; 17 ll C[MAXN], num[MAXN]; 18 19 void init(){ 20 memset(C, 0, sizeof(C)); 21 l = 0;//l代表的是整个序列的长度 22 scanf("%lld%lld", &m, &MOD); 23 24 } 25 ll lowbit(ll x) {return x & -x;} 26 ll Max(ll l, ll r){ 27 ll cnt = num[r]; 28 while (l <= r){ 29 cnt = max(cnt, num[r]); 30 for (--r; r - l >= lowbit(r); r -= lowbit(r)) cnt = max(cnt, C[r]); 31 //cnt = max(cnt, C[r]); 32 } 33 return cnt; 34 } 35 void work(){ 36 ll last = 0;//表示上一次查询的答案 37 for (int i = 1; i <= m; i++){ 38 char str[2]; 39 scanf("%s", str); 40 if (str[0] == 'Q'){ 41 int a; 42 scanf("%lld", &a); 43 last = Max(l - a + 1, l); 44 printf("%lld ", last);//[a,l]区间内的最大值 45 }else{ 46 ll x; 47 scanf("%lld", &x); 48 num[++l] = (x + last) % MOD; 49 C[l] = max(Max(l - lowbit(l) + 1, l - 1), (x + last) % MOD); 50 51 } 52 } 53 } 54 55 int main(){ 56 int T; 57 #ifdef LOCAL 58 freopen("data.txt", "r", stdin); 59 freopen("out.txt", "w", stdout); 60 #endif 61 init(); 62 work(); 63 return 0; 64 }