【BZOJ4825】【HNOI2017】单旋(线段树,set)

90 篇文章 0 订阅
31 篇文章 0 订阅

Description

click me


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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值