[NOI2005] to maintain the number of columns --Splay

Face questions

  Luo Gu P2042

Resolve

    This question is most Splay assembly of the classic operation, wys in class the teacher talked about, this topic is still very worth doing

  Exercise group:

    Splay operations on all sections required extraction interval, if you want to extract a [l, r] interval, need only point to l-1 is the root, then r + 1 point to the root of the right son, then left and right son of the son of the sub-tree root whole pieces of what we want to extract the interval

  Operation 1: Insert

    The question is not inserted insert a number, but a number of columns inserted, one by one, will certainly be inserted T, so put the number of columns inserted before the completion of a tree, and then extract the interval, when his son left his son the right to the root of son left empty, just put the new root of the tree roots hanging in the right son, last updated information to

  Action 2: Delete

    Or the first extraction interval, the right side off the root of the son and the son of its left connected to the line, but the limited space of this question, you need to recover the node number, it is best to open a stack to store numbers, with the queue, then a waste of space, and must be open to a large array on CodeVS AC, it does not seem to differ in Los Valley, of course, I mean handwritten queue queue, you impress me with STL

  Operation 3: Modify

    The same is the first extraction interval, the root of the left and right son's son marked mark once in a while

  Operation 4: Flip

    Extraction interval, the root of the left and right son's son marked mark after modification

  Action 5: sum

    Extraction interval, output

  Operation 6: sum of the maximum and subsequence

    Finally do extraction interval, and direct output on the line. But when the maintenance information is very troublesome, and the largest sub-segment tree columns similar sum, we need to maintain maximum interval sequences, and the maximum range of about subsequence and, at the time of the update up, you need to operate like this which is the left son of x ls, rs is the right son, MX and is the largest sub-sequences and, lx is the largest sub-interval sequence of the left and, rx is the right range and maximum subsequence

  detail:

       0 nodes mx assigned to negative infinity, because some point no son left or right son, to avoid making mistakes (director wys tune the details of one hour) when updating the answer

    When the next pass mark should note that there is no left or right son, son, or change the information node 0, I do half an hour

    Stretching operation (splay) Do not write hung up, I did a one hour

  Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 500005, inf = 0x3f3f3f3f;

template<class T> void read(T &re)
{
    re=0;
    T sign=1;
    char tmp;
    while((tmp=getchar())&&(tmp<'0'||tmp>'9')) if(tmp=='-') sign=-1;
    re=tmp-'0';
    while((tmp=getchar())&&(tmp>='0'&&tmp<='9')) re=(re<<3)+(re<<1)+(tmp-'0');
    re*=sign;
}

int n, m, root, id[maxn], tot;
int a[maxn];

struct splay_tree{
    int s[2], siz, fa, tag;
    int val, mx, lx, rx, sum, c;
    void init(int x)
    {
        val = sum = mx = x;
        lx = rx = max(x, 0);
        siz = 1;
        c = inf;
    }
    void Clear()
    {
        s[0] = s[1] = siz = fa = tag = 0;
        val = lx = rx = sum = mx = 0;
        c = inf;
    }
}tr[maxn];

int stak[maxn], top;

void update(int x)
{
    int ls = tr[x].s[0], rs = tr[x].s[1];
    tr[x].sum = tr[ls].sum + tr[rs].sum + tr[x].val;
    tr[x].siz = tr[ls].siz + tr[rs].siz + 1;
    tr[x].mx = max(tr[ls].mx, tr[rs].mx);
    tr[x].mx = max(tr[x].mx, tr[ls].rx + tr[rs].lx + tr[x].val);
    tr[x].lx = max(tr[ls].lx, tr[ls].sum + tr[x].val + tr[rs].lx);
    tr[x].rx = max(tr[rs].rx, tr[rs].sum + tr[x].val + tr[ls].rx);
}

void spread(int x)
{
    int ls = tr[x].s[0], rs = tr[x].s[1];
    if(tr[x].c != inf)
    {
        if(ls)
        {
            tr[ls].val = tr[ls].c = tr[x].c;
            tr[ls].sum = tr[ls].siz * tr[x].c;
            tr[ls].lx = tr[ls].rx = max(tr[ls].sum, 0);
            tr[ls].mx = max(tr[ls].val, tr[ls].sum);
        }
        if(rs)
        {
            tr[rs].val = tr[rs].c = tr[x].c;
            tr[rs].sum = tr[rs].siz * tr[x].c;
            tr[rs].lx = tr[rs].rx = max(tr[rs].sum, 0);
            tr[rs].mx = max(tr[rs].val, tr[rs].sum);
        }
        tr[x].c = inf;
        tr[x].tag = 0;
    }
    if(tr[x].tag)
    {
        if(ls)
        {
            tr[ls].tag ^= 1;
            swap(tr[ls].lx, tr[ls].rx);
            swap(tr[ls].s[0], tr[ls].s[1]);
        }
        if(rs)
        {
            tr[rs].tag ^= 1;
            swap(tr[rs].lx, tr[rs].rx);
            swap(tr[rs].s[0], tr[rs].s[1]);
        }
        tr[x].tag = 0;
    }
}

void Rotate(int x)
{
    int y = tr[x].fa, z = tr[y].fa, k = (tr[y].s[1] == x), w = (tr[z].s[1] == y), son = tr[x].s[k^1];
    tr[y].s[k] = son;tr[son].fa = y;
    tr[x].s[k^1] = y;tr[y].fa = x;
    tr[z].s[w] = x;tr[x].fa = z;
    update(y);update(x);
}

void Splay(int x, int to)
{
    while(tr[x].fa != to)
    {
        int y = tr[x].fa, z = tr[y].fa;
        if(z == to)
        {
            Rotate(x);
            break;
        }
        Rotate((tr[y].s[1] == x) != (tr[z].s[1] == y) ? x: y);
        Rotate(x);
    }
    if(!to)
        root = x;
}

int Find(int x)
{
    int now = root;
    while(1)
    {
        spread(now);
        int ls = tr[now].s[0], rs = tr[now].s[1];
        if(x == tr[ls].siz + 1)     return now;
        if(x <= tr[ls].siz)     now = ls;
        else x -= tr[ls].siz + 1,  now = rs;
    }
}

void build(int l, int r,  int f)
{
    int mid = (l + r)>>1, now = id[mid], pre = id[f];
    if(l == r)
        tr[now].init(a[mid]);
    if(l < mid)
        build(l, mid - 1, mid);
    if(mid < r)
        build(mid + 1, r, mid);
    tr[now].val = a[mid];
    tr[now].fa = pre;
    tr[now].c = inf;
    update(now);
    tr[pre].s[mid >= f] = now;
}

void Insert(int pos, int len)
{
    for( int i = 1; i <= len; ++i)
        read(a[i]);
    for( int i = 1; i <= len; ++i)
        if(top)
            id[i] = stak[top--];
        else
            id[i] = ++tot;
    build(1, len, 0);
    int x = id[(1+len)>>1];
    int y = Find(pos + 1), z = Find(pos + 2);
    Splay(y, 0);Splay(z, y);
    tr[x].fa = z;
    tr[z].s[0] = x;
    update(z);update(y);
}

void Recycle( int x)
{
    if(!x)    return ;
    int ls = tr[x].s[0], rs = tr[x].s[1];
    stak[++top] = x;
    tr[x].Clear();
    if(ls)    Recycle(ls);
    if(rs)    Recycle(rs);
}

void Del(int pos, int len)
{
    int x = Find(pos), y = Find(pos + len + 1);
    Splay(x, 0);Splay(y, x);
    Recycle(tr[y].s[0]);
    tr[y].s[0] = 0;
    update(y);update(x);
}

void Change(int pos, int len, int val)
{
    int x = Find(pos), y = Find(pos + len + 1);
    Splay(x, 0);Splay(y, x);
    int z = tr[y].s[0];
    tr[z].val = tr[z].c = val;
    tr[z].sum = tr[z].siz * val;
    tr[z].lx = tr[z].rx = max(tr[z].sum, 0);
    tr[z].mx = max(tr[z].val, tr[z].sum);
    update(y);update(x);
}

void Rever(int pos, int len)
{
    int x = Find(pos), y = Find(pos + len + 1);
    Splay(x, 0);Splay(y, x);
    int z = tr[y].s[0];
    if(tr[z].c == inf)
    {
        tr[z].tag ^= 1;
        swap(tr[z].lx, tr[z].rx);
        swap(tr[z].s[0], tr[z].s[1]);
        update(y);update(x);
    }
}

int Query(int pos, int len)
{
    int x = Find(pos), y = Find(pos + len + 1);
    Splay(x, 0);Splay(y, x);
    int z = tr[y].s[0];
    return tr[z].sum;
}

int main()
{
    read(n);read(m);
    tr[0].mx = a[1] = a[n+2] = -inf;
    for( int i = 1; i <= n; ++i)
        read(a[i+1]);
    for( int i = 1; i <= n + 2; ++i)
        id[i] = i;
    build(1, n + 2, 0);
    root = (n + 3)>>1;
    tot = n + 2;
    for( int i = 1; i <= m; ++i)
    {
        char opt[10];
        int pos, len;
        scanf("%s", opt);
        if(opt[0] == 'I')
        {
            read(pos);read(len);
            Insert(pos, len);
        }
        else if(opt[0] == 'D')
        {
            read(pos);read(len);
            Del(pos, len);
        }
        else if(opt[0] == 'M' && opt[2] == 'K')
        {
            int val;
            read(pos);read(len);read(val);
            Change(pos, len, val);
        }
        else if(opt[0] == 'R')
        {
            read(pos);read(len);
            Rever(pos, len);
        }
        else if(opt[0] == 'G')
        {
            read(pos);read(len);
            printf("%d\n", Query(pos, len));
        }
        else
            printf("%d\n", tr[root].mx);        
    }
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/Joker-Yza/p/11224430.html