zoukankan      html  css  js  c++  java
  • BZOJ1500 : [NOI2005]维修数列-fhq_Treap


    题面见这里

    反正是道平衡树,就拿 fhq_Treap 写了写...

    这道题思路基本是围绕“用 Treap 维护中序遍历” 和 中序遍历的性质 来进行的操作

    所以就可以类比线段树进行一些操作

    1. 建树 & 插入

      这题也要用到笛卡尔树的建树方式,假的 O(n) 真是相当快啊

      建树的方式见这里

    inline int build(int r) {
        top = 0;
        register int tmp = newnode(a[1]);
        stk[++top] = tmp;
        for(int i = 2; i <= r; ++i) {
            int last = 0, cur = newnode(a[i]);
            while(top and t[stk[top]].prio > t[cur].prio) {
                pushup(stk[top]);
                last = stk[top];
                stk[top--] = 0;
            }
            t[cur].ch[0] = last;
            pushup(cur);
            if(top) {
                t[stk[top]].ch[1] = cur;
                pushup(stk[top]);
            }
            stk[++top] = cur;
        }
        while(top) pushup(stk[top--]);
        return stk[1];
    }

      在本题中呢,由于插入的值不是一个一个给出的而是给出序列,故应先建出一棵小 Treap 再合并过去

      在这里也要用到上面提到的方式来建这棵小树

    inline void Insert(int pos, int tot) {
        int newrt = build(tot);
        pair<int, int> x = Split(Root, pos);
        Root = Merge(Merge(x.first, newrt), x.second);
        return;
    }
    

    2.删除

      此题的删除也是删除一段序列,直接 Split 出来即可

      不过这里注意到任何时刻数列中最多含有 5e5 个数,多写一个内存回收就好了

    inline int Malloc(){
        register int x;
        return (!delpool.empty()) ? (t[x = delpool.front()].clear(), delpool.pop(), x) : (++poolcur); 
    }
    inline int newnode(int val) {
        register int cur = Malloc();
        t[cur].val = t[cur].sum = t[cur].prtmx = val;
        t[cur].lmx = t[cur].rmx = max(0, val);
        t[cur].prio = rand();
        t[cur].siz = 1;
        return cur;
    }
    void Recycle(int cur) {
        if(!cur) return;
        if(lson) Recycle(lson);
        delpool.push(cur);
        if(rson) Recycle(rson);
        return;
    }
    inline void Remove(int pos, int tot) {
        pair<int, int> x = Split(Root, pos + tot - 1);
        pair<int, int> y = Split(x.first, pos - 1);
        Recycle(y.second);
        Root = Merge(y.first, x.second);
        return;
    }

      觉得递归不优美的可以手写栈模拟

    3.区间修改

      打标记

    inline void cover(int pos, int tot, int val) {
        pair<int, int> x = Split(Root, pos + tot - 1);
        pair<int, int> y = Split(x.first, pos - 1);
        t[y.second].val = t[y.second].cvr = val;
        t[y.second].sum = val * t[y.second].siz;
        t[y.second].lmx = t[y.second].rmx = max(0, t[y.second].sum);
        t[y.second].prtmx = max(t[y.second].val, t[y.second].sum);
        t[y.second].rvrs = false;
        Root = Merge(Merge(y.first, y.second), x.second);
        return;
    }
    

     

    4.翻转区间

      比较基础的操作

    inline void Reverse(int pos, int tot) {
        pair<int, int> x = Split(Root, pos + tot - 1);
        pair<int, int> y = Split(x.first, pos - 1);
        t[y.second].rvrs ^= 1;
        swap(t[y.second].lmx, t[y.second].rmx);
        swap(t[y.second].ch[0], t[y.second].ch[1]);
        Root = Merge(Merge(y.first, y.second), x.second);
        return;
    }
    

    5.求和 & 最大子段和

      这里一开始不敢这么写,其实是可以的

      在提取一个区间的过程中,是在不断 pushup 和 pushdown 的,故提取/合并后并不会出什么差错

      像线段树一样维护,一些维护的的值在 Reverse 后注意更新

    inline void rvrs(int cur) {
        swap(lson, rson);
        swap(t[cur].lmx, t[cur].rmx);
        t[cur].rvrs ^= 1;
        return;
    }
    inline void cvr(int cur, int val) {
        t[cur].cvr = t[cur].val = val;
        t[cur].sum = t[cur].siz * val;
        t[cur].prtmx = max(t[cur].val, t[cur].sum);
        t[cur].lmx = t[cur].rmx = max(0, t[cur].sum);
        return;
    }
    inline void pushup(int cur) {
        t[cur].siz = t[lson].siz + t[rson].siz + 1;
        t[cur].sum = t[cur].val + t[lson].sum + t[rson].sum;
        t[cur].lmx = max(0, max(t[lson].lmx, t[lson].sum + t[rson].lmx + t[cur].val));
        t[cur].rmx = max(0, max(t[rson].rmx, t[rson].sum + t[lson].rmx + t[cur].val));
        t[cur].prtmx = max(t[cur].val, t[lson].rmx + t[rson].lmx + t[cur].val);
        if(lson) t[cur].prtmx = max(t[cur].prtmx, t[lson].prtmx);
        if(rson) t[cur].prtmx = max(t[cur].prtmx, t[rson].prtmx);
        return;
    }
    inline void pushdown(int cur) {
        if(t[cur].rvrs) {
            if(lson) rvrs(lson);
            if(rson) rvrs(rson);
        }
        if(t[cur].cvr != inf) {
            if(lson) cvr(lson, t[cur].cvr);
            if(rson) cvr(rson, t[cur].cvr);
        }
        t[cur].rvrs = false;
        t[cur].cvr = inf;
        return;
    }

      

    完整的代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<ctime>
    #define lson t[cur].ch[0]
    #define rson t[cur].ch[1]
    using namespace std;
    
    const int MAXN = 500010, inf = 2333;
    
    struct Node{
        int ch[2], siz, val, prio, lmx, rmx, sum, prtmx;
        int cvr;
        bool rvrs;
        Node(){ch[0] = ch[1] = siz = val = sum = 0; cvr = inf; rvrs = false;}
        void clear(){
            ch[0] = ch[1] = siz = val = sum = 0;
            cvr = inf;
            rvrs = false;
            return;
        }
    }t[MAXN];
    int n, m, poolcur, Root;
    int a[MAXN], stk[MAXN], top;
    queue<int> delpool;
    char que[20];
    
    inline int Malloc(){
        register int x;
        return (!delpool.empty()) ? (t[x = delpool.front()].clear(), delpool.pop(), x) : (++poolcur); 
    }
    inline int newnode(int val) {
        register int cur = Malloc();
        t[cur].val = t[cur].sum = t[cur].prtmx = val;
        t[cur].lmx = t[cur].rmx = max(0, val);
        t[cur].prio = rand();
        t[cur].siz = 1;
        return cur;
    }
    inline void pushup(int cur) {
        t[cur].siz = t[lson].siz + t[rson].siz + 1;
        t[cur].sum = t[cur].val + t[lson].sum + t[rson].sum;
        t[cur].lmx = max(0, max(t[lson].lmx, t[lson].sum + t[rson].lmx + t[cur].val));
        t[cur].rmx = max(0, max(t[rson].rmx, t[rson].sum + t[lson].rmx + t[cur].val));
        t[cur].prtmx = max(t[cur].val, t[lson].rmx + t[rson].lmx + t[cur].val);
        if(lson) t[cur].prtmx = max(t[cur].prtmx, t[lson].prtmx);
        if(rson) t[cur].prtmx = max(t[cur].prtmx, t[rson].prtmx);
        return;
    }
    inline void rvrs(int cur) {
        swap(lson, rson);
        swap(t[cur].lmx, t[cur].rmx);
        t[cur].rvrs ^= 1;
        return;
    }
    inline void cvr(int cur, int val) {
        t[cur].cvr = t[cur].val = val;
        t[cur].sum = t[cur].siz * val;
        t[cur].prtmx = max(t[cur].val, t[cur].sum);
        t[cur].lmx = t[cur].rmx = max(0, t[cur].sum);
        return;
    }
    inline void pushdown(int cur) {
        if(t[cur].rvrs) {
            if(lson) rvrs(lson);
            if(rson) rvrs(rson);
        }
        if(t[cur].cvr != inf) {
            if(lson) cvr(lson, t[cur].cvr);
            if(rson) cvr(rson, t[cur].cvr);
        }
        t[cur].rvrs = false;
        t[cur].cvr = inf;
        return;
    }
    inline int build(int r) {
        top = 0;
        register int tmp = newnode(a[1]);
        stk[++top] = tmp;
        for(int i = 2; i <= r; ++i) {
            int last = 0, cur = newnode(a[i]);
            while(top and t[stk[top]].prio > t[cur].prio) {
                pushup(stk[top]);
                last = stk[top];
                stk[top--] = 0;
            }
            t[cur].ch[0] = last;
            pushup(cur);
            if(top) {
                t[stk[top]].ch[1] = cur;
                pushup(stk[top]);
            }
            stk[++top] = cur;
        }
        while(top) pushup(stk[top--]);
        return stk[1];
    }
    pair<int, int> Split(int cur, int k) {
        if(!cur or !k) return make_pair(0, cur);
        pushdown(cur);
        pair<int, int> res;
        if(t[lson].siz >= k) {
            res = Split(lson, k);
            lson = res.second;
            pushup(cur);
            res.second = cur;
        } else {
            res = Split(rson, k - t[lson].siz - 1);
            rson = res.first;
            pushup(cur);
            res.first = cur;
        }
        return res;
    }
    int Merge(int x, int y) {
        if(x) pushdown(x); if(y) pushdown(y);
        if(!x) return y; if(!y) return x;
        if(t[x].prio < t[y].prio) {
            t[x].ch[1] = Merge(t[x].ch[1], y);
            pushup(x);
            return x;
        } else {
            t[y].ch[0] = Merge(x, t[y].ch[0]);
            pushup(y);
            return y;
        }
    }
    void Recycle(int cur) {
        if(!cur) return;
        if(lson) Recycle(lson);
        delpool.push(cur);
        if(rson) Recycle(rson);
        return;
    }
    inline void Insert(int pos, int tot) {
        int newrt = build(tot);
        pair<int, int> x = Split(Root, pos);
        Root = Merge(Merge(x.first, newrt), x.second);
        return;
    }
    inline void Remove(int pos, int tot) {
        pair<int, int> x = Split(Root, pos + tot - 1);
        pair<int, int> y = Split(x.first, pos - 1);
        Recycle(y.second);
        Root = Merge(y.first, x.second);
        return;
    }
    inline void Reverse(int pos, int tot) {
        pair<int, int> x = Split(Root, pos + tot - 1);
        pair<int, int> y = Split(x.first, pos - 1);
        t[y.second].rvrs ^= 1;
        swap(t[y.second].lmx, t[y.second].rmx);
        swap(t[y.second].ch[0], t[y.second].ch[1]);
        Root = Merge(Merge(y.first, y.second), x.second);
        return;
    }
    inline void cover(int pos, int tot, int val) {
        pair<int, int> x = Split(Root, pos + tot - 1);
        pair<int, int> y = Split(x.first, pos - 1);
        t[y.second].val = t[y.second].cvr = val;
        t[y.second].sum = val * t[y.second].siz;
        t[y.second].lmx = t[y.second].rmx = max(0, t[y.second].sum);
        t[y.second].prtmx = max(t[y.second].val, t[y.second].sum);
        t[y.second].rvrs = false;
        Root = Merge(Merge(y.first, y.second), x.second);
        return;
    }
    inline int getsum(int pos, int tot) {
        pair<int, int> x = Split(Root, pos + tot - 1);
        pair<int, int> y = Split(x.first, pos - 1);
        int ans = t[y.second].sum;
        Root = Merge(Merge(y.first, y.second), x.second);
        return ans;
    }
    void rdstr(char s[]) {
        register int sz = 0;
        register char c = getchar();
        while(!isalpha(c) and c != '-') c = getchar();
        while(isalpha(c) || (c == '-')) {
            s[sz++] = c;
            c = getchar();
        }
        return;
    }
    inline int rd() {
        register int x = 0;
        register char c = getchar();
        register bool f = false;
        while(!isdigit(c)) {
            if(c == '-') f = true;
            c = getchar();
        }
        while(isdigit(c)) {
            x = x * 10 + (c ^ 48);
            c = getchar();
        }
        return f ? -x : x;
    }
    
    int main() {
        srand(time(NULL));
        n = rd(); m = rd();
        for(int i = 1; i <= n; ++i) a[i] = rd();
        Root = build(n);
        int pos, tot, val;
        while(m--) {
            rdstr(que);
            switch(que[0]) {
                case 'I':{
                    pos = rd(); tot = rd();
                    for(int i = 1; i <= tot; ++i) a[i] = rd();
                    Insert(pos, tot);
                    break;
                }
                case 'D':{
                    pos = rd(); tot = rd();
                    Remove(pos, tot);
                    break;
                }
                case 'R':{
                    pos = rd(); tot = rd();
                    Reverse(pos, tot);
                    break;
                }
                case 'G':{
                    pos = rd(); tot = rd();
                    printf("%d
    ", getsum(pos, tot));
                    break;
                }
                case 'M':{
                    if(que[2] == 'K') {
                        pos = rd(); tot = rd(); val = rd();
                        cover(pos, tot, val);
                    } else {
                        printf("%d
    ", t[Root].prtmx);
                    }
                    break;
                }
            }
        }
        return 0;
    }
    

      

    禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载 ,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
  • 相关阅读:
    【Selenium04篇】python+selenium实现Web自动化:文件上传,Cookie操作,调用 JavaScript,窗口截图
    【Selenium03篇】python+selenium实现Web自动化:元素三类等待,多窗口切换,警告框处理,下拉框选择
    【Selenium02篇】python+selenium实现Web自动化:鼠标操作和键盘操作!
    【Selenium01篇】python+selenium实现Web自动化:搭建环境,Selenium原理,定位元素以及浏览器常规操作!
    面试官看到一定会打我---软件测试工程师面试套路和暗语灵魂解密
    十年测试老鸟告诉你--自动化测试选JAVA还是选Python--写给还在迷茫中的朋友
    华为十年测试老鸟教您如何便写高质量的自动化测试工程师简历--看完必有所获
    工作中常用的Android系统ADB命令收集
    自动化测试中的三类等待深入剥析
    JAVA自动化之Junit单元测试框架详解
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9090704.html
Copyright © 2011-2022 走看看