【JSOI2008】最大数
https://www.luogu.org/problem/show?pid=1198
之前刚学完Splay想找题练手的时候做的,写完Splay交上去了才发现这应该是线段树裸题23333
Splay解法
按照要求操作即可……
#include <iostream> using namespace std; int m, d, t; const int inf = 0x7fffffff; namespace splay { struct node; node *nil = 0, *root; struct node { int val, size, maxnum; node *ch[2]; node(int v) : val(v), size(1), maxnum(v) { ch[0] = ch[1] = nil; } void pull_up() { size = ch[0]->size + ch[1]->size + 1; maxnum = max(val, max(ch[0]->maxnum, ch[1]->maxnum)); } int cmp(int k) { if(this == nil || k == ch[0]->size + 1) return -1; else return (k <= ch[0]->size) ? 0 : 1; } }; void init() { if(!nil) nil = new node(-inf); nil->size = 0; nil->ch[0] = nil->ch[1] = nil; root = new node(-inf); root->ch[1] = new node(-inf); root->size = 2; } void rotate(node *&t, int d) { node *k = t->ch[d ^ 1]; t->ch[d ^ 1] = k->ch[d]; k->ch[d] = t; t->pull_up(); k->pull_up(); t = k; } void splay(int k, node *&t = root) { int d1 = t->cmp(k); if(d1 == 1) k = k - t->ch[0]->size - 1; if(d1 != -1) { int d2 = t->ch[d1]->cmp(k); if(d2 != -1) { int k2 = (d2 == 1) ? (k - t->ch[d1]->ch[0]->size - 1) : k; splay(k2, t->ch[d1]->ch[d2]); if(d1 != d2) { rotate(t->ch[d1], d2 ^ 1); rotate(t, d1 ^ 1); } else { rotate(t, d1 ^ 1); rotate(t, d2 ^ 1); } } else rotate(t, d1 ^ 1); } } void insert(int val) { splay(root->size - 1); node *k = root->ch[1]; root->ch[1] = new node(val); root->ch[1]->ch[1] = k; k->pull_up(); root->ch[1]->pull_up(); root->pull_up(); } int get_maxnum(int len) { int from = root->size - len; int to = from + len - 1; splay(to + 1, root); splay(from - 1, root->ch[0]); return root->ch[0]->ch[1]->maxnum; } } int main() { using namespace splay; cin >> m >> d; init(); char a; int b; while(m--) { cin >> a >> b; switch(a) { case 'A': insert((b + t) % d); break; case 'Q': t = get_maxnum(b); cout << t << endl; break; } } return 0; }
线段树解法
M<=2e5,也就是极限状况下最多2e5个数。开个长度是2e5的线段树,再记录下已经加了N个数了。每次插入就是更改第N+1个元素,查询就是查询区间[N-L+1,N]的最大值。
懒得重写一遍了……