AOJ 1070 FIMO sequence
制約条件
クエリの数≦200000
方針
結構前に解いた奴なので忘れてる。
データ構造を、前半(n + 1) / 2個と後半n / 2個の二つに分けて持つ。
前半の数列で、末尾からk項を削除したときの最小値、最大値を求めるには、
増加列からなるデキューと、減少列からなるデキューとを使えばよい。
要素の挿入と削除増加列の中身のsetと、減少列の中身のsetを使って何かしてる……
ソースコード
const int MX = 400010; int n, type, in[MX]; struct S{ int *q, *inc, *dec, h, t, ih, it, dh, dt; set<pair<int, int> > incs, decs; S(){ q = new int[MX]; inc = new int[MX]; dec = new int[MX]; h = t = ih = it = dh = dt = MX / 2; } ~S(){ delete(q); delete(inc); delete(dec); } int size(){ return t - h; } void push(int id){ q[t++] = id; if(ih < it && in[inc[it - 1]] >= in[id]) incs.insert(mp(-in[id], id)); else inc[it++] = id; if(dh < dt && in[dec[dt - 1]] <= in[id]) decs.insert(mp( in[id], id)); else dec[dt++] = id; } int pop(){ int id = q[--t]; set<pair<int, int> >::iterator p = incs.lower_bound(mp(-in[id], 0)); set<pair<int, int> >::iterator q = decs.lower_bound(mp( in[id], 0)); if(p != incs.end() && p -> second == id) incs.erase(p); if(q != decs.end() && q -> second == id) decs.erase(q); if(ih < it && inc[it - 1] == id){ it--; if(!incs.empty() && -incs.begin()->first > in[inc[it - 1]]) inc[it++] = incs.begin()->second; } if(dh < dt && dec[dt - 1] == id){ dt--; if(!decs.empty() && decs.begin()->first < in[dec[dt - 1]]) dec[dt++] = decs.begin()->second; } return in[id]; } int get(int x){ return in[dec[dt - x]]; } int rget(int x){ return in[inc[it - x]]; } }; struct T{ int *q, *inc, *dec, h, t, ih, it, dh, dt; T(){ q = new int[MX]; inc = new int[MX]; dec = new int[MX]; h = t = ih = it = dh = dt = MX / 2; } ~T(){ delete(q); delete(inc); delete(dec); } int size(){ return t - h; } void push(int id){ while(ih < it && in[inc[it - 1]] >= in[id]) it--; while(dh < dt && in[dec[dt - 1]] <= in[id]) dt--; q[t++] = inc[it++] = dec[dt++] = id; } int pop(){ if(ih < it && inc[ih] == q[h]) ih++; if(dh < dt && dec[dh] == q[h]) dh++; return q[h++]; } int get(int x){ return in[inc[ih + x - 1]]; } int rget(int x){ return in[dec[dh + x - 1]]; } }; const bool next[] = {1, 0, 0, 0, 1, 1, 0, 0, 1, 1}; int main(){ while(cin >> n, n){ S s; T t; rep(it, n){ cin >> type; if(next[type]) cin >> in[it]; if(type == 0){ t.push(it); if(s.size() < t.size()) s.push(t.pop()); } else if(type == 1){ cout << s.pop() << endl; if(s.size() < t.size()) s.push(t.pop()); } else if(type == 2) cout << s.get(1) << endl; else if(type == 3) cout << t.get(1) << endl; else if(type == 4) cout << s.get(in[it]) << endl; else if(type == 5) cout << t.get(in[it]) << endl; else if(type == 6) cout << s.rget(1) << endl; else if(type == 7) cout << t.rget(1) << endl; else if(type == 8) cout << s.rget(in[it]) << endl; else if(type == 9) cout << t.rget(in[it]) << endl; } cout << "end" << endl; } return 0; }