zoukankan      html  css  js  c++  java
  • [HNOI2017]单旋

    题意:

    模拟一棵单旋splay,支持五种操作

    ( ext{Solution:})

    显然不是让你码一颗单旋splay(一条链卡爆你)。

    在草稿纸上画一画,模拟一遍,观察中序遍历下的深度变化,发现当x为最小值时它没有左儿子,可能有右儿子,splay到根后除了它的右儿子深度不变,其余的深度都+1,x为最大值时同理。

    因此,每次操作我们都可以用线段树直接维护深度,接下来要解决的问题就是怎么插入。

    二叉搜索树一个点总是插在其前驱的右儿子或是后继的左儿子

    所以我们只要找到它前驱或后继,然后接在它的下面,这个过程很容易用set实现,还要记录每个点的左儿子以及右儿子是谁,不然无法判断插入到前驱和后继哪个下面去。

    ( ext{Source})

    // luogu-judger-enable-o2
    #include <set>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <assert.h>
    #include <algorithm>
    
    using namespace std;
    
    #define LL long long
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define GO debug("GO
    ")
    
    inline int rint() {
      register int x = 0, f = 1; register char c;
      while (!isdigit(c = getchar())) if (c == '-') f = -1;
      while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getchar()));
      return x * f;
    }
    
    template<typename T> inline void chkmin(T &a, T b) { a > b ? a = b : 0; }
    template<typename T> inline void chkmax(T &a, T b) { a < b ? a = b : 0; }
    
    const int N = 1e5 + 10;
    
    #define Iter set<int>::iterator
    set<int> S;
    int a[N], tot, ch[N][2], fa[N], m, op[N], buc[N], root; int dep[N<<2];
    
    void add(int x, int l, int r, int L, int R, int val) {
      if (L <= l and r <= R) {
        dep[x] += val;
        return;
      }
      int mid = (l + r) >> 1;
      if (L <= mid) add(x<<1, l, mid, L, R, val);
      if (mid < R) add(x<<1|1, mid + 1, r, L, R, val);
    }
    
    int query(int x, int l, int r, int p) {
      if (l == r) {
        return dep[x];
      }
      int mid = (l + r) >> 1;
      if (p <= mid) return dep[x] + query(x<<1, l, mid, p);
      else return dep[x] + query(x<<1|1, mid+1, r, p);
    }
    
    void change(int x, int y) {
      add(1, 1, tot, x, x, y - query(1, 1, tot, x));
    }
    
    int Insert(int x) {
      Iter it = S.insert(x).first;
      if (root == 0) {
        root = x;
        change(x, 1);
        return 1;
      }
      if (it != S.begin()) {
        if (ch[*--it][1] == 0) ch[fa[x] = *it][1] = x;
        it++;
      }
      if (fa[x] == 0) ch[fa[x] = *++it][0] = x;
      int res = query(1, 1, tot, fa[x]) + 1;
      change(x, res);
      return res;
    }
    
    int findmin() {
      int x = *S.begin(), res = query(1, 1, tot, x);
      if (x == root) return 1;
      if (x + 1 <= fa[x] - 1)
        add(1, 1, tot, x + 1, fa[x] - 1, -1);
      add(1, 1, tot, 1, tot, 1);
      ch[fa[x]][0] = ch[x][1], fa[ch[x][1]] = fa[x];
      fa[root] = x, ch[x][1] = root;
      root = x;
      change(x, 1);
      return res;
    }
    
    int findmax() {
      int x = *S.rbegin(), res = query(1, 1, tot, x);
      if (x == root) return 1;
      if (x - 1 >= fa[x] + 1)
        add(1, 1, tot, fa[x] + 1, x - 1, -1);
      add(1, 1, tot, 1, tot, 1);
      ch[fa[x]][1] = ch[x][0], fa[ch[x][0]] = fa[x];
      fa[root] = x, ch[x][0] = root;
      root = x;
      change(x, 1);
      return res;
    }
    
    void delmin() {
      printf("%d
    ", findmin());
      add(1, 1, tot, 1, tot, -1);
      S.erase(root);
      root = ch[root][1];
      fa[root] = 0;
    }
    
    void delmax() {
      printf("%d
    ", findmax());
      add(1, 1, tot, 1, tot, -1);
      S.erase(root);
      root = ch[root][0];
      fa[root] = 0;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
      freopen("xhc.in", "r", stdin);
      freopen("xhc.out", "w", stdout);
    #endif
      m = rint();
      for (int i = 1; i <= m; ++ i) {
        op[i] = rint();
        if (op[i] == 1) {
          tot++;
          a[tot] = buc[tot] = rint();
        }
      }
      sort(buc + 1, buc + 1 + tot);
      for (int i = 1; i <= tot; ++ i)
        a[i] = lower_bound(buc + 1, buc + 1 + tot, a[i]) - buc;
      for (int i = 1, cnt = 0; i <= m; ++ i) {
        switch(op[i]) {
        case 1: printf("%d
    ", Insert(a[++cnt])); break;
        case 2: printf("%d
    ", findmin()); break;
        case 3: printf("%d
    ", findmax()); break;
        case 4: delmin(); break;
        case 5: delmax(); break;
        }
      }
    }
    
    
  • 相关阅读:
    一个晚上加一个上午啊 笨死算球
    转来的——python webdriver自动化测试初步印象——转来的
    MySQL软件升级
    创建rhel7基础镜像
    SHELL-收集Oracle已应用的PSU信息
    rhel7.6上安装Oracle 19.2.0.0 RAC
    AIX平台安装Oracle11gR2数据库
    Oracle Database(rdbms) 12.2 安装组件
    HP-UX平台安装Oracle11gR2数据库
    Linux平台安装Oracle11gR2数据库
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/10594663.html
Copyright © 2011-2022 走看看