Description
Solution
手玩发现每次去最大、最小值也就是直接将该节点放到根节点,插入值就是将节点插入到该键值的前驱后继中深度最大的那个的下方。
然后用std::set
维护深度,用,线段树维护深度即可。
Code
/**************************************
* Au: Hany01
* Prob: [BZOJ4825][HNOI2017] 单旋
* Date: Apr 6th, 2018
* Email: hany01@foxmail.com
**************************************/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef vector<int> VI;
#define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
#define rep(i, j) for (register int i = 0, i##_end_ = j; i < i##_end_; ++ i)
#define For(i, j ,k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define SZ(a) ((int)(a.size()))
#define ALL(a) a.begin(), a.end()
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define Mod (1000000007)
#define y1 wozenmezhemecaia
#ifdef hany01
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif
template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
inline int read() {
register char c_; register int _, __;
for (_ = 0, __ = 1, c_ = getchar(); !isdigit(c_); c_ = getchar()) if (c_ == '-') __ = -1;
for ( ; isdigit(c_); c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
return _ * __;
}
const int maxn = 100005;
struct Opt { int ty, p; }opt[maxn];
int n, m, ls[maxn], fa[maxn], ch[maxn][2], rt;
set<int> Set;
struct SegmentTree
{
int tr[maxn << 2], tag[maxn << 2];
#define lc (t << 1)
#define rc (lc | 1)
#define mid ((l + r) >> 1)
inline void maintain(int t) { tr[t] = tr[lc] + tr[rc]; }
inline void pushdown(int t, int l, int r)
{
if (tag[t])
{
tag[lc] += tag[t], tag[rc] += tag[t];
tr[lc] += tag[t] * (mid - l + 1), tr[rc] += tag[t] * (r - mid);
tag[t] = 0;
}
}
void update(int t, int l, int r, int x, int y, int dt)
{
if (x <= l && r <= y) {
tr[t] += (r - l + 1) * dt, tag[t] += dt;
return ;
}
pushdown(t, l, r);
if (mid >= x) update(lc, l, mid, x, y, dt);
if (mid < y) update(rc, mid + 1, r, x, y, dt);
maintain(t);
}
void reset(int t, int l, int r, int x, int dt)
{
if (l == r) { tr[t] = dt; return ; }
pushdown(t, l, r);
if (x <= mid) reset(lc, l, mid, x, dt);
else reset(rc, mid + 1, r, x, dt);
maintain(t);
}
int query(int t, int l, int r, int x)
{
if (l == r) return tr[t];
pushdown(t, l, r);
if (x <= mid) return query(lc, l, mid, x);
else return query(rc, mid + 1, r, x);
}
}st;
int main()
{
#ifdef hany01
File("bzoj4825");
#endif
m = read();
For(i, 1, m)
if ((opt[i].ty = read()) == 1) ls[++ n] = opt[i].p = read();
sort(ls + 1, ls + 1 + n);
n = unique(ls + 1, ls + 1 + n) - ls - 1;
For(i, 1, m) if (opt[i].ty == 1) opt[i].p = lower_bound(ls + 1, ls + 1 + n, opt[i].p) - ls;
For(i, 1, m)
{
if (opt[i].ty == 1)
{
register int u = opt[i].p;
Set.insert(u);
if (SZ(Set) == 1) st.reset(1, 1, n, u, 1), rt = u, puts("1");
else if (Set.lower_bound(u) == Set.begin()) {
int tmp = *Set.upper_bound(u);
int dep = st.query(1, 1, n, tmp);
ch[tmp][0] = u, fa[u] = tmp, st.reset(1, 1, n, u, dep + 1);
printf("%d\n", dep + 1);
} else if (Set.upper_bound(u) == Set.end()) {
int tmp = *--Set.lower_bound(u);
int dep = st.query(1, 1, n, tmp);
ch[tmp][1] = u, fa[u] = tmp, st.reset(1, 1, n, u, dep + 1);
printf("%d\n", dep + 1);
} else {
int tmp1 = *Set.upper_bound(u), tmp2 = *--Set.lower_bound(u);
int dep1, dep2;
dep1 = st.query(1, 1, n, tmp1), dep2 = st.query(1, 1, n, tmp2);
if (dep1 > dep2) ch[tmp1][0] = u, fa[u] = tmp1, st.reset(1, 1, n, u, dep1 + 1);
else ch[tmp2][1] = u, fa[u] = tmp2, st.reset(1, 1, n, u, dep2 + 1);
printf("%d\n", max(dep1, dep2) + 1);
}
} else if (opt[i].ty == 2)
{
int u = *Set.begin();
printf("%d\n", st.query(1, 1, n, u));
if (u == rt) continue;
if (fa[u]) st.update(1, 1, n, fa[u], n, 1);
st.reset(1, 1, n, u, 1);
if (ch[u][1]) fa[ch[u][1]] = fa[u];
if (fa[u]) ch[fa[u]][0] = ch[u][1];
fa[u] = 0;
ch[u][1] = rt, fa[rt] = u, rt = u;
} else if (opt[i].ty == 3)
{
int u = *--Set.end();
printf("%d\n", st.query(1, 1, n, u));
if (u == rt) continue;
if (fa[u]) st.update(1, 1, n, 1, fa[u], 1);
st.reset(1, 1, n, u, 1);
if (ch[u][0]) fa[ch[u][0]] = fa[u];
if (fa[u]) ch[fa[u]][1] = ch[u][0];
fa[u] = 0;
ch[u][0] = rt, fa[rt] = u, rt = u;
} else if (opt[i].ty == 4)
{
int u = *Set.begin();
printf("%d\n", st.query(1, 1, n, u));
if (rt == u) {
Set.erase(Set.begin());
rt = ch[u][1];
st.update(1, 1, n, 1, n, -1);
continue;
}
if (ch[u][1]) st.update(1, 1, n, 1, fa[u] - 1, -1);
if (ch[u][1]) fa[ch[u][1]] = fa[u];
ch[fa[u]][0] = ch[u][1];
Set.erase(Set.begin());
} else
{
int u = *--Set.end();
printf("%d\n", st.query(1, 1, n, u));
if (rt == u) {
Set.erase(--Set.end());
rt = ch[u][0];
st.update(1, 1, n, 1, n, -1);
continue;
}
if (ch[u][0]) st.update(1, 1, n, fa[u] + 1, n, -1);
if (ch[u][0]) fa[ch[u][0]] = fa[u];
ch[fa[u]][1] = ch[u][0];
Set.erase(*--Set.end());
/*For(i, 1, n) cout << fa[i] << ' ';
cout << endl;
For(i, 1, n) cout << st.query(1, 1, n, i) << ' ';
cout << endl;
For(i, 1, n) cout <<ch[i][0] << ' ' << ch[i][1] << endl;*/
}
}
return 0;
}