POJ 3580 SuperMemo
TreapをVerifyするために解いた。
#include <string> #include <vector> #include <algorithm> #include <set> #include <map> #include <queue> #include <iostream> #include <sstream> #include <cstdio> #include <cmath> #include <ctime> #include <cstring> #include <cassert> #define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i)) #define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i)) #define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i)) #define each(it,o) for(aut(it, (o).begin()); it != (o).end(); ++ it) #define all(o) (o).begin(), (o).end() #define pb(x) push_back(x) #define mp(x,y) make_pair((x),(y)) #define mset(m,v) memset(m,v,sizeof(m)) using namespace std; typedef long long ll; typedef vector<int> vi; typedef vector<ll> vl; typedef pair<ll,ll> pll; typedef vector<pll> vpll; typedef vector<string> vs; const int INF = 0x3f3f3f3f; const ll INFL = 0x3f3f3f3f3f3f3f3fLL; typedef int Val; struct Node { Val val; int priority; Node *ch[2]; //ここに欲しい情報(値のsum, 値のmin, etc.) //splitのためにデフォルトでsizeがある int size; Val mini; //遅延評価をするもの Val add; bool rev; //情報の初期値を設定する Node(Val v, int p) : val(v), priority(p) , size(1), add(0), rev(false), mini(v) { ch[0] = ch[1] = NULL; } }; //NULL用に関数を作っておくと便利(Nodeのコンストラクタと同じく初期値に注意) //addをvalやminiにも足している点に注意。こんなふうにできないと遅延評価はできない Val val(Node *x) { assert(x); return x->val + x->add; } int size(Node *x) { return !x ? 0 : x->size; } Val mini(Node *x) { return !x ? INF : x->mini + x->add; } Node *update(Node *x) { //ここで情報の更新を行う if(!x) return x; x->size = size(x->ch[0]) + 1 + size(x->ch[1]); x->mini = min(min(mini(x->ch[0]), mini(x->ch[1])), val(x)); if(x->add) { x->val += x->add; if(x->ch[0]) x->ch[0]->add += x->add; if(x->ch[1]) x->ch[1]->add += x->add; x->add = 0; } if(x->rev) { swap(x->ch[0], x->ch[1]); if(x->ch[0]) x->ch[0]->rev ^= 1; if(x->ch[1]) x->ch[1]->rev ^= 1; x->rev = false; } return x; } Node *link(Node *x, Node *c, bool b) { x->ch[b] = c; return update(x); } Node *merge(Node *x, Node *y) { x = update(x); y = update(y); if(!x || !y) return x ? x : y; if(x->priority < y->priority) { return link(x, merge(x->ch[1], y), 1); }else { return link(y, merge(x, y->ch[0]), 0); } } //サイズによってsplitする。 ([0,k) , [k,n)) typedef pair<Node*, Node*> NPair; NPair split(Node *t, int k) { if(!update(t)) return mp((Node*)NULL, (Node*)NULL); if(size(t->ch[0]) < k) { NPair u = split(t->ch[1], k - size(t->ch[0]) - 1); return mp(link(t, u.first, 1), u.second); }else { NPair u = split(t->ch[0], k); return mp(u.first, link(t, u.second, 0)); } } Node *singleton(Val val) { return update(new Node(val, rand())); } int main() { int n; scanf("%d", &n); Node *t = NULL; rep(i, n) { Val a; scanf("%d", &a); t = merge(t, singleton(a)); } int m; scanf("%d", &m); rep(i, m) { static char s[100]; int x, y, a; scanf("%s", s); rep(i, 10) s[i] = toupper(s[i]); if(s[0] == 'A') { scanf("%d%d%d", &x, &y, &a); x--; NPair p = split(t, x); NPair q = split(p.second, y-x); q.first->add += a; t = merge(p.first, merge(q.first, q.second)); }else if(s[0] == 'R' && s[3] == 'E') { scanf("%d%d", &x, &y); x--; NPair p = split(t, x); NPair q = split(p.second, y-x); q.first->rev ^= 1; t = merge(p.first, merge(q.first, q.second)); }else if(s[0] == 'R' && s[3] == 'O') { scanf("%d%d%d", &x, &y, &a); x--; a %= (y - x); NPair p = split(t, x); NPair q = split(p.second, y-x); Node *m = q.first; NPair r = split(m, size(m) - a); t = merge(p.first, merge(merge(r.second, r.first), q.second)); }else if(s[0] == 'I') { scanf("%d%d", &x, &a); NPair p = split(t, x); t = merge(p.first, merge(singleton(a), p.second)); }else if(s[0] == 'D') { scanf("%d%d", &x); x--; NPair p = split(t, x); NPair q = split(p.second, 1); delete q.first; t = merge(p.first, q.second); }else if(s[0] == 'M') { scanf("%d%d", &x, &y); x--; NPair p = split(t, x); NPair q = split(p.second, y-x); printf("%d\n", mini(q.first)); t = merge(p.first, merge(q.first, q.second)); } } return 0; }