zoukankan      html  css  js  c++  java
  • 【题解】【loj120】持久化序列

    由于UT并不会可持久化平衡树,因此他决定用一种奇怪的方法AC此题。

    空间:线性

    缺点:离线。

    首先,每个更新/查询都是基于一个历史版本的。

    查询先不管,就看更新,相当于每个点有一个“父亲”,总的形成一个树结构(!

    每个更新,相当于树上的一条边。

    然后转回来处理查询,可以认为是在每个节点后面拖了一串询问。

    那接着怎么做相信应该不难想到了吧?维护一棵平衡树然后dfs此更新树~

    向下的时候,相当于直接操作。

    回溯的时候,相当于是撤销了一条边上的操作。

    看看操作,一加一删,正好支持撤销~

    加变删,删变加(临时存一下被删掉的数)就好了。

    然后,每进入到一个节点的时候,就把拖着的一串询问回答掉。

    Over~

    细节基本没有。

    方便起见,使用了fhq-treap。

    然后就是挫代码了(

    #include <bits/stdc++.h>
    #pragma GCC optimize("Ofast", 3, "inline")
    #pragma comment(linker, "/STACK:102400000,102400000")
    using namespace std;
    const int N = 1e6 + 9;
    mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
    struct node {
      int val;
      unsigned rnd;
      int l, r;
      int sz;
    } tree[N];
    int tot, root;
    int newnode(int x) {
      tree[++tot] = (node){x, rnd(), 0, 0, 1};
      return tot;
    }
    void pushup(int x) { tree[x].sz = tree[tree[x].l].sz + tree[tree[x].r].sz + 1; }
    void split(int now, int k, int& l, int& r) {
      if (!now) {
        l = r = 0;
        return;
      }
      if (tree[tree[now].l].sz < k) {
        l = now;
        split(tree[now].r, k - tree[tree[now].l].sz - 1, tree[now].r, r);
      } else {
        r = now;
        split(tree[now].l, k, l, tree[now].l);
      }
      pushup(now);
    }
    int merge(int x, int y) {
      if (!x) return y;
      if (!y) return x;
      if (tree[x].rnd < tree[y].rnd) {
        tree[x].r = merge(tree[x].r, y);
        return pushup(x), x;
      } else {
        tree[y].l = merge(x, tree[y].l);
        return pushup(y), y;
      }
    }
    int kth(int k) {
      int now = root;
      while (1) {
        int dl = tree[tree[now].l].sz;
        if (k <= dl)
          now = tree[now].l;
        else if (k > dl + 1)
          now = tree[now].r, k -= dl + 1;
        else
          return tree[now].val;
      }
    }
    void insert_t_as_kth(int t, int k) {
      int x, y;
      split(root, k - 1, x, y);
      root = merge(merge(x, newnode(t)), y);
    }
    void delete_kth(int k) {
      int x, y, z;
      split(root, k - 1, x, y);
      split(y, 1, y, z);
      root = merge(x, z);
    }
    void print(int now) {
      if (!now) return;
      print(tree[now].l);
      printf("%d ", tree[now].val);
      print(tree[now].r);
    }
    void print() {
      print(root);
      putchar('
    ');
    }
    const int __N__ = 3e5 + 9;
    int fa[__N__], op[__N__], k[__N__], t[__N__];
    int id[__N__];
    vector<int> out[__N__];
    vector<int> query[__N__];
    int ans[N];
    int cnt;
    void dfs(int now) {
      // printf("etring #%d
    ", now);
      // print();
      for (int q : query[now]) {
        ans[q] = kth(k[q]);
      }
      for (int to : out[now]) {
        // printf("fa:%d:", now), print();
        if (op[to] == 1) {
          insert_t_as_kth(t[to], k[to]);
          dfs(to);
          delete_kth(k[to]);
        } else {
          int x, y, z;
          split(root, k[to] - 1, x, y);
          split(y, 1, y, z);
          int tmp = tree[y].val;
          root = merge(x, z);
          dfs(to);
          insert_t_as_kth(tmp, k[to]);
        }
      }
    }
    int read() {
      char c;
      while (!isdigit(c = getchar()))
        ;
      int x = c ^ 48;
      while (isdigit(c = getchar())) x = x * 10 + (c ^ 48);
      return x;
    }
    int main() {
      memset(ans, -1, sizeof ans);
      int m;
      scanf("%d", &m);
      for (int i = 1; i <= m; ++i) {
        scanf("%d%d%d", op + i, fa + i, k + i);
        // printf("fa[%d]=%d,id[%d]=%d;
    ", i, fa[i], fa[i], id[fa[i]]);
        if (op[i] == 1) scanf("%d", t + i);
        if (op[i] != 3)
          id[++cnt] = i, out[id[fa[i]]].push_back(i);
        else
          query[id[fa[i]]].push_back(i);
      }
      dfs(0);
      for (int i = 1; i <= m; ++i)
        if (~ans[i]) printf("%d
    ", ans[i]);
      return 0;
    }
    
  • 相关阅读:
    微信小程序
    如何在微信小程序中使用骨架屏
    Nlog打印日志到Influxdb数据库
    C#通过模板导出Word的两种方法(超简单)
    VS2019制作的安装包,默认安装到C盘快捷方式无法打开
    orcale数据库还原备份
    Thread 类创建线程
    Quartz.NET
    DataTable ,使用详细。
    Unity3D 学习
  • 原文地址:https://www.cnblogs.com/unyieldingtrilobite/p/13933985.html
Copyright © 2011-2022 走看看