zoukankan      html  css  js  c++  java
  • 牛客-Forsaken的数列(Treap)

    题目传送门

    sol:第一次看题还真信了是用线段树来做,但是没什么想法,看了题解发现是我不会的Treap,然后花了几天时间学习了一下并补掉题目

    • 无旋Treap
      #include <bits/stdc++.h>
      using namespace std;
      typedef long long LL;
      const int MAXN = 2e5 + 10;
      struct Treap {
          int ls, rs;
          int rand, size;
          LL sum, val, lazy;
      } node[MAXN];
      int root, tot;
      int add_node(int v) {
          int i = ++tot;
          node[i].ls = node[i].rs = 0;
          node[i].rand = rand();
          node[i].sum = node[i].val = v;
          node[i].lazy = 0;
          node[i].size = 1;
          return i;
      }
      void push_down(int rt) {
          int ls = node[rt].ls;
          int rs = node[rt].rs;
          if (ls != 0) {
              node[ls].lazy += node[rt].lazy;
              node[ls].val += node[rt].lazy;
              node[ls].sum += node[ls].size * node[rt].lazy;
          }
          if (rs != 0) {
              node[rs].lazy += node[rt].lazy;
              node[rs].val += node[rt].lazy;
              node[rs].sum += node[rs].size * node[rt].lazy;
          }
          node[rt].lazy = 0;
      }
      void push_up(int rt) {
          int ls = node[rt].ls;
          int rs = node[rt].rs;
          node[rt].size = node[ls].size + node[rs].size + 1;
          node[rt].sum = node[ls].sum + node[rs].sum + node[rt].val;
      }
      void split(int rt, int& a, int& b, int s) {
          if (rt == 0) {
              a = b = 0;
              return;
          }
          push_down(rt);
          int size = node[node[rt].ls].size;
          if (size < s) {
              a = rt;
              split(node[rt].rs, node[a].rs, b, s - size - 1);
          } else {
              b = rt;
              split(node[rt].ls, a, node[b].ls, s);
          }
          push_up(rt);
      }
      void merge(int& rt, int a, int b) {
          if (a == 0 || b == 0) {
              rt = a + b;
              return;
          }
          push_down(a);
          push_down(b);
          if (node[a].rand < node[b].rand) {
              rt = a;
              merge(node[rt].rs, node[a].rs, b);
          } else {
              rt = b;
              merge(node[rt].ls, a, node[b].ls);
          }
          push_up(rt);
      }
      void insert(int p, int v) {
          int x = 0, y = 0;
          split(root, x, y, p - 1);
          merge(root, x, add_node(v));
          merge(root, root, y);
      }
      void add(int l, int r, int v) {
          int x = 0, y = 0, z = 0;
          split(root, root, z, r);
          split(root, x, y, l - 1);
          node[y].lazy += v;
          node[y].val += v;
          node[y].sum += node[y].size * v;
          merge(root, x, y);
          merge(root, root, z);
      }
      LL query(int l, int r) {
          int x = 0, y = 0, z = 0;
          split(root, root, z, r);
          split(root, x, y, l - 1);
          LL sum = node[y].sum;
          merge(root, x, y);
          merge(root, root, z);
          return sum;
      }
      int main() {
          int n, q;
          scanf("%d", &n);
          for (int i = 1; i <= n; i++) {
              int v; scanf("%d", &v);
              merge(root, root, add_node(v));
          }
          scanf("%d", &q);
          for (int i = 1; i <= q; i++) {
              int opt; scanf("%d", &opt);
              if (opt == 1) {
                  int pos; scanf("%d", &pos);
                  insert(pos, 0);
              } else if (opt == 2) {
                  int l, r, v;
                  scanf("%d%d%d", &l, &r, &v);
                  add(l, r, v);
              } else {
                  int l, r;
                  scanf("%d%d", &l, &r);
                  printf("%lld
      ", query(l, r));
              }
          }
          return 0;
      }

      在前置知识都掌握的情况下Treap还是挺好懂的,而且之前感觉lazy标记挺乱的,看了这题之后感觉理清了

  • 相关阅读:
    拷贝目录下文件,但某种类型文件例外
    编译个性化的openwrt固件
    -exec和|xargs
    OpenMP多线程linux下的使用,简单化
    clock_gettime的使用,计时比clock()精确
    openvswitch安装和使用 --修订通用教程的一些错误
    树莓派配置AP模式
    win7下的mstsc ubuntu下的rdesktop
    微信小程序-商品列表左=>右联动
    Vue.js最佳实践(五招让你成为Vue.js大师)
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/11803932.html
Copyright © 2011-2022 走看看