Description
http://codevs.cn/problem/2573/
题解:
学SBT时因为某些原因半途而废,今天碰到平衡树裸题,就重新练一遍吧。读入add和get数组后,可以模拟出操作序列。仅用到SBT的旋转、maintain、插入和第k大的操作。
代码里大部分是SBT模板。
CODE:
/*
time :49ms;
memory :1M;
*/
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 50000;
int key[maxn], s[maxn], lc[maxn], rc[maxn];
int n, m, tot, root;
int add[30001], get[30001];
inline void rr(int &t) {
int k = lc[t];
lc[t] = rc[k];
rc[k] = t;
s[k] = s[t];
s[t] = s[lc[t]]+s[rc[t]]+1;
t = k;
}
inline void lr(int &t) {
int k = rc[t];
rc[t] = lc[k];
lc[k] = t;
s[k] = s[t];
s[t] = s[lc[t]]+s[rc[t]]+1;
t = k;
}
void maintain(int &t, bool flag) {
if(!flag)
if(s[lc[lc[t]]] > s[rc[t]]) rr(t);
else if(s[rc[lc[t]]] > s[rc[t]]) {
lr(lc[t]);
rr(t);
}
else return;
else if(s[rc[rc[t]]] > s[lc[t]]) lr(t);
else if(s[lc[rc[t]]] > s[lc[t]]) {
rr(rc[t]);
lr(t);
}
else return;
maintain(lc[t], false);
maintain(rc[t], true);
maintain(t, true);
maintain(t, false);
}
void insert(int &t, int v) {
if(t == 0) {
++tot;
t = tot;
key[t] = v;
s[t] = 1;
lc[t] = rc[t] = 0;
}
else {
++s[t];
if(v < key[t]) insert(lc[t], v);
else insert(rc[t], v);
maintain(t, v>=key[t]);
}
}
int select(int &t, int k) {
if(k == s[lc[t]]+1) return key[t];
if(k <= s[lc[t]]) return select(lc[t], k);
else return select(rc[t], k-1-s[lc[t]]);
}
int main() {
scanf("%d%d", &m, &n);
for(int i = 1; i <= m; ++i) scanf("%d", &add[i]);
for(int i = 1; i <= n; ++i) scanf("%d", &get[i]);
int lst = 1, now = 1;
for(int iter = 1; iter <= n; ++iter) {
for(int i = now; i <= get[iter]; ++i)
insert(root, add[i]);
now = get[iter]+1;
printf("%d\n", select(root, lst));
++lst;
}
return 0;
}