zoukankan      html  css  js  c++  java
  • [NOI2005]维护数列

    就放一个 Splay 平衡树板子…… 感觉总算理解一点了……
     
    破题调了两天多,最后是用第一天第一遍写的代码改了维护一个变量的方法,然后就 A 了……
     
    咱写的 Splay 有一点缺陷,就是每个叶子节点下面还挂着两个不产生贡献的空节点;不过对渐进复杂度都没什么影响,而且可以防止莫名的 RE。
     

    #include <cmath>
    #include <stack>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define lch child[0]
    #define rch child[1]
    
    const int maxn = 1000000 + 10;
    int n, m, a[maxn], node_num; char ques[11];
    
    inline int read() {
      register int ch = 0; register int w = 0, x = 0;
      for( ; !isdigit(ch); w = w | (ch == '-'), ch = getchar()) ;
      for( ; isdigit(ch); x = (x * 10) + (ch ^ 48), ch = getchar()) ;
      return w ? -x : x;
    }
    
    struct Node {
      int id;
      int size, val, sum, set, rev, lef_max, rig_max, all_max;
      Node *child[2], *pre;
      Node() { size = val = sum = rev = lef_max = rig_max = 0, all_max = -maxn, set = maxn, pre = child[0] = child[1] = NULL; }
      ~Node() {};
    } *p_root, node[maxn], clear;
    
    std::stack<Node*> bin;
    
    class Splay {
    public:
      inline void Maintain(Node *root) {
        root->size = root->lch->size + root->rch->size + 1;
        root->sum = root->lch->sum + root->rch->sum + root->val;
        root->lef_max = max(root->lch->lef_max, root->lch->sum + root->val + root->rch->lef_max);
        root->rig_max = max(root->rch->rig_max, root->rch->sum + root->val + root->lch->rig_max);
        root->all_max = max(max(root->lch->all_max, root->rch->all_max), root->lch->rig_max + root->val + root->rch->lef_max);
      }
    
      inline void Pushdown(Node *root) {
        if( root->rev ) {
          swap(root->lch->lch, root->lch->rch), swap(root->lch->lef_max, root->lch->rig_max);
          swap(root->rch->lch, root->rch->rch), swap(root->rch->lef_max, root->rch->rig_max);
          root->lch->rev = root->lch->rev ^ 1, root->rch->rev = root->rch->rev ^ 1, root->rev = 0;
        }
        if( root->set != maxn ) {
          root->lch->val = root->set, root->lch->sum = root->set * root->lch->size;
          root->rch->val = root->set, root->rch->sum = root->set * root->rch->size;
          if( root->set > 0 ) {
            root->lch->lef_max = root->lch->rig_max = root->lch->all_max = root->lch->size * root->set;
            root->rch->lef_max = root->rch->rig_max = root->rch->all_max = root->rch->size * root->set;
          }
          else {
            root->lch->lef_max = root->lch->rig_max = 0, root->lch->all_max = root->set;
            root->rch->lef_max = root->rch->rig_max = 0, root->rch->all_max = root->set;
          }
          root->lch->set = root->rch->set = root->set, root->set = maxn;
        }
      }
    
      inline bool Choosech(Node *root) { return root->pre->rch == root; }
    
      inline void Rotate(Node *root) {
        Node *p = root->pre;
        bool pos = Choosech(root);
        Pushdown(p), Pushdown(root), p->child[pos] = root->child[!pos];
        if( root->child[!pos] ) root->child[!pos]->pre = p;
        if( root->pre = p->pre ) root->pre->child[Choosech(p)] = root;
        p->pre = root, root->child[!pos] = p;
        Maintain(p), Maintain(root);
        if( root->pre == NULL ) p_root = root;
      }
    
      inline void Spaly(Node *root, Node *posi) {
        Node *p = root->pre;
        while( (p = root->pre) != posi ) {
          if( p->pre != posi ) Rotate(Choosech(root) == Choosech(p) ? p : root);
          Rotate(root);
        }
      }
    
      inline Node* Findnode(Node *root, int k) {
        int tmp = 0;
        root = p_root;
        while( true ) {
          Pushdown(root);
          if( root->lch && k <= root->lch->size ) { root = root->lch; continue; }
          tmp = (root->lch ? root->lch->size : 0) + 1;
          if( k <= tmp ) return root;
          k = k - tmp, root = root->rch;
        }
      }
    
      inline void Build(Node *root, int l, int r) {
        if( l > r ) return ;
        int mid = (l + r) >> 1;
        root->val = root->sum = root->all_max = a[mid], root->lef_max = root->rig_max = max(0, a[mid]), root->size = 1;
        if( bin.empty() ) root->lch = &node[++node_num]; else root->lch = bin.top(), bin.pop();
        root->lch->pre = root, Build(root->lch, l, mid - 1);
        if( bin.empty() ) root->rch = &node[++node_num]; else root->rch = bin.top(), bin.pop();
        root->rch->pre = root, Build(root->rch, mid + 1, r);
        if( l < r ) Maintain(root);
      }
    
      inline void Retrie(Node *root) {
        if( root->lch ) Retrie(root->lch);
        if( root->rch ) Retrie(root->rch);
        *root = clear, bin.push(root);
      }
    
      inline void Insert(int x, int len) {
        for(int i = 1; i <= len; ++i) a[i] = read();
        Node *p = NULL;
        p = Findnode(p_root, x), Spaly(p, NULL), p = Findnode(p_root, x + 1), Spaly(p, p_root);
        Retrie(p->lch), p->lch = bin.top(), bin.pop();
        n = n + len, p->lch->pre = p, Build(p->lch, 1, len), Maintain(p), Maintain(p->pre);
      }
    
      inline void Delete(int x, int len) {
        Node *p = NULL;
        p = Findnode(p_root, x - 1), Spaly(p, NULL), p = Findnode(p_root, x + len), Spaly(p, p_root);
        Retrie(p->lch), p->lch = bin.top(), bin.pop();
        n = n - len, p->lch->pre = p, Maintain(p), Maintain(p->pre);
      }
    
      inline void Revers(int x, int len) {
        Node *p = NULL;
        p = Findnode(p_root, x - 1), Spaly(p, NULL), p = Findnode(p_root, x + len), Spaly(p, p_root);
        p->lch->rev = p->lch->rev ^ 1;
        swap(p->lch->lch, p->lch->rch), swap(p->lch->lef_max, p->lch->rig_max);
      }
    
      inline void Getsum(int x, int len) {
        Node *p = NULL;
        p = Findnode(p_root, x - 1), Spaly(p, NULL), p = Findnode(p_root, x + len), Spaly(p, p_root);
        printf("%d
    ", p->lch->sum);
      }
    
      inline void Setnum(int x, int len, int c) {
        Node *p = NULL;
        p = Findnode(p_root, x - 1), Spaly(p, NULL), p = Findnode(p_root, x + len), Spaly(p, p_root);
        p->lch->set = c, p->lch->val = p->lch->set, p->lch->sum = len * p->lch->set;
        if( p->lch->set > 0 ) p->lch->lef_max = p->lch->rig_max = p->lch->all_max = len * p->lch->set;
        else p->lch->lef_max = p->lch->rig_max = 0, p->lch->all_max = c;
      }
    
      inline void Maxsum() {
        Node *p = NULL;
        p = Findnode(p_root, 1), Spaly(p, NULL), p = Findnode(p_root, n), Spaly(p, p_root);
        printf("%d
    ", p->lch->all_max);
      }
    } tree;
    
    inline void Print(Node *root) {
      if( root->size > 1 ) tree.Pushdown(root);
      if( root->lch ) Print(root->lch);
      if( root->val ) printf("%d ", root->val);
      if( root->rch ) Print(root->rch);
      if( root->size > 1 ) tree.Maintain(root);
    }
    
    int main(int argc, char const *argv[])
    {
      scanf("%d%d", &n, &m);
      for(int i = 1; i <= n; ++i) a[i + 1] = read();
      p_root = &node[++node_num], tree.Build(p_root, 1, n + 2);
      n = n + 2;
      for(int x, len, i = 1; i <= m; ++i) {
        scanf("%s", ques);
        switch( ques[0] ^ ques[2] ) {
          case ('I' ^ 'S' ): x = read() + 1, len = read(), tree.Insert(x, len); break;
          case ('D' ^ 'L' ): x = read() + 1, len = read(), tree.Delete(x, len); break;
          case ('R' ^ 'V' ): x = read() + 1, len = read(), tree.Revers(x, len); break;
          case ('G' ^ 'T' ): x = read() + 1, len = read(), tree.Getsum(x, len); break;
          case ('M' ^ 'K' ): x = read() + 1, len = read(), tree.Setnum(x, len, read()); break;
          case ('M' ^ 'X' ): tree.Maxsum(); break;
          default : break;
        }
        // Node *p = NULL;
        // p = tree.Findnode(p_root, 1), tree.Spaly(p, NULL), p = tree.Findnode(p_root, n), tree.Spaly(p, p_root);
        // Print(p->lch), printf("
    ");
      }
    
      return 0;
    }
    
  • 相关阅读:
    0325JavaScript
    0322css样式表,选择器
    0320表单
    0313函数
    0312数组
    0311类
    0309笔记整理
    进制转换
    Xcode快捷键大全
    Android LearningNotes
  • 原文地址:https://www.cnblogs.com/nanjoqin/p/11236275.html
Copyright © 2011-2022 走看看