[NOI2005]维护数列

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

#include 
#include 
#include 
#include 
#include 
#include 
#include 
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 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\n", 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\n", 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("\n");
  }

  return 0;
}

你可能感兴趣的:([NOI2005]维护数列)