洛谷P1198 [JSOI2008]最大数
传送门
题意
自己看原题啊
题解
直接建一颗有 $M$ 个节点的线段树,然后单点修改、区间查询最大值即可。
时间复杂度: $\mathcal O(m \mathrm{lg} m)$ 。
上代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 struct SgTree{ 5 #define segc int M = L + R - 1 >> 1, lc = id << 1, rc = lc | 1 6 int sz; 7 struct node {int v, f; bool zero;} *x; 8 SgTree (): sz(0) {x = NULL;} 9 ~SgTree () {if(x) delete [] (x);} 10 void resize(int size) {sz = size; int sz0 = sz << 3; if(x) delete [] (x); 11 x = new node[sz0]; memset(x, 0, sz0 * sizeof(node));} 12 13 void add(int h, int v) {add(1, 1, sz, h, v);} 14 int range(int l, int r) {return query(1, 1, sz, l, r);} 15 16 void add(int id, int L, int R, int h, int v){ 17 if(L == R) return void(x[id].v += v); 18 segc; h <= M ? add(lc, L, M, h, v) : add(rc, M + 1, R, h, v); 19 x[id].v = max(x[lc].v, x[rc].v); 20 } 21 22 int query(int id, int L, int R, int ql, int qr){ 23 if(ql <= L && R <= qr) return x[id].v; 24 segc, s = 0; 25 if(ql <= M) s = max(s,query(lc, L, M, ql, min(qr, M))); 26 if(qr > M) s = max(s,query(rc, M + 1, R, max(ql, M + 1), qr)); 27 return s; 28 } 29 } ST; 30 31 int main() { 32 ios :: sync_with_stdio(false); 33 int m, d, lastans = 0; 34 cin >> m >> d; 35 ST.resize(m); int n = 0; 36 while (m--) { 37 char op[5]; int v; 38 cin >> op >> v; 39 if (op[0] == 'Q') { 40 cout << (lastans = ST.range(max(1, n-v+1), n)) << endl; 41 } else { 42 ++n; ST.add(n, (v + lastans) % d); 43 } 44 } 45 return 0; 46 }