序列终结者 Splay

1.注意在 split merge时要特判一下边界, 否则就会出现边界错误的情况。

2.随时都要维护父指针。
3.在更新 maxv
 和翻转标记时要判一下左右儿子是否都存在。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 100000 + 3;
int f[maxn], ch[maxn][2], n,m,numv[maxn], maxv[maxn], siz[maxn], tag[maxn], root, cnt , lazy[maxn];
struct Operation 
{
    inline int get(int x){ return ch[f[x]][1] == x; }
    inline void pushdown(int x)
    {
        if(tag[x]) 
        {
            swap(ch[ch[x][0]][0],ch[ch[x][0]][1]); 
            swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
            if(ch[x][0]) tag[ch[x][0]] ^= 1;
            if(ch[x][1]) tag[ch[x][1]] ^= 1;
            tag[x] = 0;
        }
        if(lazy[x])
        {
            if(ch[x][0]) maxv[ch[x][0]] += lazy[x], lazy[ch[x][0]] += lazy[x], numv[ch[x][0]] += lazy[x];
            if(ch[x][1]) maxv[ch[x][1]] += lazy[x], lazy[ch[x][1]] += lazy[x], numv[ch[x][1]] += lazy[x];
            lazy[x] = 0;
        }
    }
    inline void pushup(int x)
    {
        siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
        maxv[x] = numv[x];
        if(ch[x][0]) maxv[x] = max(maxv[x], maxv[ch[x][0]]);
        if(ch[x][1]) maxv[x] = max(maxv[x], maxv[ch[x][1]]);
    }
    inline void rotate(int x)
    {
        int old = f[x], oldf = f[old], which = get(x);
        ch[old][which] = ch[x][which ^ 1], f[ch[old][which]] = old;
        ch[x][which ^ 1] = old, f[old] = x, f[x] = oldf;
        if(oldf) ch[oldf][ch[oldf][1] == old] = x;
        pushup(old); pushup(x);
    }
    inline void splay(int x,int &tar)
    {
        int a = f[tar];
        for(int fa; (fa = f[x]) != a; rotate(x))
            if(f[fa] != a) rotate(get(x) == get(fa) ? fa : x);
        tar = x;
    }
    inline int findx(int x, int top)
    {
        int cur = top;
        while(x > 0)
        {
            pushdown(cur);
            int ls = ch[cur][0], rs = ch[cur][1];
            if(siz[ls] + 1 == x) return cur;
            if(siz[ls] >= x) cur = ls;
            else x -= siz[ls] + 1, cur = rs;
        }
        return 0;
    }
    inline void split(int &a,int nums,int &b)
    {
        if(nums == 0)
        {
            b = a, a = 0; return ;
        }
        if(nums == siz[a])
        {
            b = 0; return ;
        }
        int u = findx(nums, a);
        splay(u, a);
        b = ch[a][1];
        f[ch[a][1]] = 0, ch[a][1] = 0, 
        pushup(a);
    }
    inline void merge(int &a,int b)
    {
        if(!a) { a = b; return ;}
        splay(findx(siz[a], a), a);
        ch[a][1] = b, f[b] = a;
        pushup(a);
    }
    void build(int l,int r,int &o,int fa)
    {
        if(l > r) return ;
        o = ++cnt;
        f[o] = fa, siz[o] = 1;
        int mid = (l + r) >> 1;
        build(l, mid - 1, ch[o][0], o);
        build(mid + 1, r, ch[o][1], o);
        pushup(o);
    }
}T;
int main()
{
    //freopen("input.txt","r",stdin);
    scanf("%d%d",&n,&m);
    T.build(1, n, root, 0);
    while(m--)
    {
        int ops, l , r, v = 0;
        scanf("%d%d%d",&ops,&l,&r);
        int a = 0, b = 0; 
        T.split(root, l - 1, a);
        T.split(a, r - l + 1, b);
        if(ops == 1)
        {
            scanf("%d",&v);
            maxv[a] += v, lazy[a] += v, numv[a] += v;
            T.pushup(a);
        }
        if(ops == 2)
        {
            swap(ch[a][0], ch[a][1]);
            tag[a] ^= 1;
        }
        if(ops == 3)
        {
            printf("%d\n",maxv[a]);
        }
        T.merge(root, a);
        T.merge(root, b);
    }
    return 0;
}

  

posted @ 2018-09-18 12:44  EM-LGH  阅读(218)  评论(0编辑  收藏  举报