写了那么多XX树和单调队列后,不如试试爽翻天的倍(R)增(M)吧(Q)。
对于每一个点,维护从它为起点向左2^j长度的最大值。
查询的时候从大往小枚举2^j更新最大值就行。
(等等好像代码注释里面写过这些了)
(不保证代码的正确性。。。反正洛谷的数据水过了。。。)
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <vector> 7 8 using namespace std; 9 10 typedef long long ll; 11 12 char s[10]; 13 ll m, d, a[300000], f[300000][30], x, p, t; 14 15 /* 16 f[i][j] : 从i开始,往左2^j长度的最大值。 17 f[i][0] = a[i] 18 f[i][j] = max(f[i][j - 1], f[i - (1 << (j - 1))][j - 1]) 19 20 1 2 3 4 5 6 7 8 21 */ 22 23 ll ask(int L, int p){ 24 ll ret = -0x3f3f3f3f; 25 while(L){ 26 for(int i = 25 ; i >= 0 ; i --){ 27 if((1 << i) <= L && (p - (1 << i) + 1) >= 1){ 28 ret = max(ret, f[p][i]); 29 p -= 1 << i; 30 L -= 1 << i; 31 break; 32 } 33 } 34 } 35 return ret; 36 } 37 38 int main(){ 39 scanf("%lld%lld", &m, &d); 40 while(m --){ 41 scanf("%s%lld", s, &x); 42 if(*s == 'Q'){ 43 printf("%lld\n", t = ask(x, p)); 44 }else{ 45 a[++ p] = (x + t) % d; 46 f[p][0] = a[p]; 47 for(int i = 1 ; i <= 25 ; i ++){ 48 f[p][i] = f[p][i - 1]; 49 if(p - (1 << (i - 1)) >= 1){ 50 f[p][i] = max(f[p][i], f[p - (1 << (i - 1))][i - 1]); 51 } 52 } 53 } 54 } 55 }