zoukankan      html  css  js  c++  java
  • BZOJ 1500 维修数列

    Splay序列操作的大模板题

    这个真的是噩梦。。调了整整一个晚上,可以说完全被榨干了orz。。
    因为我的splay写的实在是太丑了,手动加的哨兵节点,开头忘记pushup了,找了一晚上才找到。。。
    还有就是0节点的mx也要设置成-INF,否则会影响我门原树叶子结点的mx。。其他的就靠造化了。。

    还要注意的是数组500000就够了,剩下的靠内存池维护,不然在BZOJ上会爆内存,但是他显示的是TLE。。不仅题目坑,这个评测也挺不友好的。。但是在洛谷还是可以过的

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    using namespace std;
    typedef long long ll;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int X = 0, w = 0; char ch = 0;
        while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
        while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
        return w ? -X : X;
    }
    inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
    inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
    template<typename T>
    inline T max(T x, T y, T z){ return max(max(x, y), z); }
    template<typename T>
    inline T min(T x, T y, T z){ return min(min(x, y), z); }
    template<typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    
    const int N = 500005;
    int ch[N][2], sum[N], mx[N], lx[N], rx[N], lazy[N], rev[N], val[N], fa[N], size[N], a[N];
    int tot, n, m, root;
    queue<int> q;
    int newNode(int p, int v){
        if(!q.empty()){
            int ret = q.front(); q.pop();
            sum[ret] = v, mx[ret] = val[ret] = v;
            if(v >= 0) lx[ret] = rx[ret] = v;
            else lx[ret] = rx[ret] = 0;
            lazy[ret] = rev[ret] = ch[ret][0] = ch[ret][1] = 0;
            fa[ret] = p, size[ret] = 1;
            return ret;
        }
        else{
            sum[++tot] = v, mx[tot] = val[tot] = v;
            if(v >= 0) lx[tot] = rx[tot] = v;
            else lx[tot] = rx[tot] = 0;
            lazy[tot] = rev[tot] = ch[tot][0] = ch[tot][1] = 0;
            fa[tot] = p, size[tot] = 1;
            return tot;
        }
    }
    
    void recycle(int x){
        if(!x) return;
        recycle(ch[x][0]);
        recycle(ch[x][1]);
        q.push(x);
    }
    
    void push_up(int x){
        int l = ch[x][0], r = ch[x][1];
        sum[x] = sum[l] + sum[r] + val[x];
        size[x] = size[l] + size[r] + 1;
        lx[x] = max(lx[l], sum[l] + val[x] + lx[r]);
        rx[x] = max(rx[r], sum[r] + val[x] + rx[l]);
        mx[x] = max(mx[l], mx[r], rx[l] + val[x] + lx[r]);
    }
    
    void push_down(int x){
        int l = ch[x][0], r = ch[x][1];
        if(lazy[x]){
            lazy[x] = rev[x] = 0;
            if(l) sum[l] = val[x] * size[l], val[l] = val[x], lazy[l] = 1;
            if(r) sum[r] = val[x] * size[r], val[r] = val[x], lazy[r] = 1;
            if(val[x] >= 0){
                if(l) lx[l] = rx[l] = mx[l] = sum[l];
                if(r) lx[r] = rx[r] = mx[r] = sum[r];
            }
            else{
                if(l) lx[l] = rx[l] = 0, mx[l] = val[x];
                if(r) lx[r] = rx[r] = 0, mx[r] = val[x];
            }
        }
        if(rev[x]){
            rev[x] ^= 1, rev[l] ^= 1, rev[r] ^= 1;
            swap(lx[l], rx[l]), swap(lx[r], rx[r]);
            swap(ch[l][0], ch[l][1]), swap(ch[r][0], ch[r][1]);
        }
    }
    
    void rotate(int x){
        int y = fa[x], z = fa[y], p = (ch[y][1] == x) ^ 1;
        push_down(y), push_down(x);
        ch[y][p^1] = ch[x][p], fa[ch[x][p]] = y;
        fa[x] = z, ch[z][ch[z][1] == y] = x, fa[y] = x, ch[x][p] = y;
        push_up(y), push_up(x);
    }
    
    void splay(int x, int goal){
        if(x == goal) return;
        while(fa[x] != goal){
            int y = fa[x], z = fa[y];
            if(z != goal){
                if((ch[y][0] == x) ^ (ch[z][0] == y)) rotate(x);
                else rotate(y);
            }
            rotate(x);
        }
        push_up(x);
        if(goal == 0) root = x;
    }
    
    int find(int k){
        if(!root) return 0;
        int cur = root, r = size[ch[cur][0]];
        while(1){
            push_down(cur);
            if(r < k){
                k -= r + 1;
                cur = ch[cur][1];
            }
            else{
                if(r > k) cur = ch[cur][0];
                else return cur;
            }
            r = size[ch[cur][0]];
        }
    }
    
    int buildTree(int p, int l, int r){
        if(l > r) return 0;
        int mid = (l + r) >> 1;
        int cur = newNode(p, a[mid]);
        ch[cur][0] = buildTree(cur, l, mid - 1);
        ch[cur][1] = buildTree(cur, mid + 1, r);
        push_up(cur);
        return cur;
    }
    
    void insert(int pos, int k){
        if(!k) return;
        for(int i = 1; i <= k; i ++) a[i] = read();
        int x = find(pos), y = find(pos + 1);
        splay(x, 0), splay(y, root);
        ch[y][0] = buildTree(y, 1, k);
        push_up(y), push_up(x);
    }
    
    void erase(int pos, int k){
        if(!k) return;
        int x = find(pos - 1), y = find(pos + k);
        splay(x, 0), splay(y, root);
        recycle(ch[y][0]);
        ch[y][0] = 0;
        push_up(y), push_up(x);
    }
    
    void modify(int pos, int k, int c){
        if(!k) return;
        int x = find(pos - 1), y = find(pos + k);
        splay(x, 0), splay(y, root);
        int key = ch[y][0];
        val[key] = c, sum[key] = size[key] * c, lazy[key] = 1;
        if(val[key] >= 0) mx[key] = lx[key] = rx[key] = sum[key];
        else mx[key] = c, lx[key] = rx[key] = 0;
        push_up(y), push_up(x);
    }
    
    void reverse(int pos, int k){
        if(!k) return;
        int x = find(pos - 1), y = find(pos + k);
        splay(x, 0), splay(y, root);
        int key = ch[y][0];
        if(!lazy[key]){
            rev[key] ^= 1;
            swap(lx[key], rx[key]), swap(ch[key][0], ch[key][1]);
            push_up(y), push_up(x);
        }
    }
    
    int getSum(int pos, int k){
        if(!k) return 0;
        int x = find(pos - 1), y = find(pos + k);
        splay(x, 0), splay(y, root);
        return sum[ch[y][0]];
    }
    
    int getMax(){
        return mx[root];
    }
    
    int main(){
    
        n = read(), m = read();
        mx[0] = -INF;
        root = newNode(0, -INF), ch[root][1] = newNode(root, -INF);
        for(int i = 1; i <= n; i ++) a[i] = read();
        ch[ch[root][1]][0] = buildTree(ch[root][1], 1, n);
        push_up(ch[root][1]), push_up(root);
        while(m --){
            char opt[20]; scanf("%s", opt);
            if(opt[2] == 'X') printf("%d
    ", getMax());
            else{
                int pos = read(), tot = read();
                if(opt[0] == 'I') insert(pos, tot);
                else if(opt[0] == 'D') erase(pos, tot);
                else if(opt[0] == 'M') { int c = read(); modify(pos, tot, c); }
                else if(opt[0] == 'R') reverse(pos, tot);
                else if(opt[0] == 'G') printf("%d
    ", getSum(pos, tot));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    AC自动机 HDOJ 2222 Keywords Search
    AC自动机 HDOJ 5384 Danganronpa
    贪心 HDOJ 5385 The Path
    区间DP UVA 10739 String to Palindrome
    区间DP UVA 10453 Make Palindrome
    素数专题
    判素数+找规律 BestCoder Round #51 (div.2) 1001 Zball in Tina Town
    DP专题
    贪心+模拟 ZOJ 3829 Known Notation
    概率DP ZOJ 3822 Domination
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/10699617.html
Copyright © 2011-2022 走看看