spoj 1470 //splay tree

1470. Another Sequence Problem

Problem code: SEQ2

You are to write a program to perform some operations on a given sequence.These operations are listed below:

---------------------------------------------------------------------------------------------
| Name        | Input format   |              function                                      |
---------------------------------------------------------------------------------------------
| Modify      | MAKE-SAME i t c| Modify all the t numbers from the ith number(included) to  |
|             |                | number c.                                                  |
---------------------------------------------------------------------------------------------
| Insert      | INSERT i t s   | Insert t numbers after the ith number.s is a sequence of t |
|             |                | numbers which should be inserted one-to-one.If i=0,you     |
|             |                | should insert s in the first of the sequence.              |
---------------------------------------------------------------------------------------------
| Delete      | DELETE i t     | Delete t numbers after the ith number(included).           |
---------------------------------------------------------------------------------------------
| Reverse     | REVERSE i t    | Reverse t numbers after the ith number(included).          |
---------------------------------------------------------------------------------------------
| Get sum     | GET-SUM i t    | Output the sum of t numbers after the ith number(included).|
---------------------------------------------------------------------------------------------
| Get maximum | MAX-SUM        | Output the maximum partial sum in the sequence now.        |
| partial sum |                |                                                            |
---------------------------------------------------------------------------------------------

See the example.

Input

The very first line contains a single integer T(T<=4), the number of test cases.T blocks follow.

For each test case:

The first line contains two integers n and m(m<=20000), the number of numbers in the sequence in the beginning and the number of operations.

The second line contains n integers seperated by spaces, the sequence in the beginning.

Next m lines, each contains an operation listed above.

You can assume that for each test case:

  • No invalid operation is in the input.
  • Number of numbers in the sequence is no more than 500000 and not less than 1 at any time.
  • All the numbers in the sequence is in range[-1000,1000] at any time.
  • The total number of numbers inserted will be not more than 4,000,000.The input is no more than 20MB.

Output

For each Get sum and Get maximum partial sum operation,you should write the answer to the output,one per line.

Example

Input:
1
9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

Output:
-1
10
1
10

Hints:

After the 3rd op., the sequence is

2 -6 3 5 1 -5 -3 6 -5 7 2 3

After the 4th op., the sequence is

2 -6 3 5 1 -5 -3 6 -5 7 2

After the 5th op., the sequence is

2 -6 2 2 2 -5 -3 6 -5 7 2

After the 6th op., the sequence is

2 -6 6 -3 -5 2 2 2 -5 7 2
Warning: enormous Input/Output data, be careful with certain languages
Added by:[Trichromatic] XilinX
Date:2007-04-01
Time limit:7s
Source limit:50000B
Languages:All except: C99 strict ERL JS
Resource:Chinese National Olympiad in Informatics 2005,Day 1; translated by lcosvse








//借鉴了网上一位大牛的代码,博客地址找不到了,在此感谢那位大牛了

#include <cstdio>
#include <cstring>
const int MAXN = 500000 + 123;
const int INF = 1 << 28;
const int NOSM = -2000;


struct node
{
    int v, c[2], p, sz, sum, sm, lmax, rmax, midmax;
    bool d, rev;
} T[MAXN + 1];

int len, front, rear, root;
int a[MAXN + 1], Q[MAXN + 1];


int max(int SS0, int SS1)
{
    return SS0 >= SS1 ? SS0 : SS1;
}

int max(int SS0, int SS1, int SS2)
{
    int M0 = SS0 >= SS1 ? SS0 : SS1;
    return M0 >= SS2 ? M0 : SS2;
}

void newnode(int n, int _v)//把以前和这个结点有关的信息全部撤掉
{
    T[n].sum = T[n].lmax = T[n].rmax = T[n].midmax = T[n].v = _v;
    T[n].c[0] = T[n].c[1] = 0;
    T[n].sz = 1;
    T[n].rev = 0;
    T[n].sm = NOSM;
}

void sm_opr(int n, int x)
{
    T[n].v = x;
    T[n].sm = x;
    T[n].sum = T[n].sz * x;
    if(x < 0) T[n].midmax = T[n].rmax = T[n].lmax = x;
    else T[n].midmax = T[n].rmax = T[n].lmax = T[n].sum;
}

void sc(int _p, int _c, bool _d)
{
    T[_p].c[_d] = _c;
    T[_c].p = _p;
    T[_c].d = _d;
}

void rev_opr(int x)
{
    T[x].rev = !T[x].rev;
    int c0 = T[x].c[0], c1 = T[x].c[1];
    sc(x, c0, 1);
    sc(x, c1, 0);
    int tmp = T[x].lmax;
    T[x].lmax = T[x].rmax;
    T[x].rmax = tmp;
}

void dm(int x)
{
    if(T[x].sm != NOSM)
    {
        sm_opr(T[x].c[0], T[x].sm);
        sm_opr(T[x].c[1], T[x].sm);
        T[x].sm = NOSM;
    }
    if(T[x].rev != 0)
    {
        rev_opr(T[x].c[0]);
        rev_opr(T[x].c[1]);
        T[x].rev = 0;
    }
}

void  upd(int x)
{
    int c0 = T[x].c[0], c1 = T[x].c[1];
    T[x].sz = T[c0].sz + T[c1].sz + 1;
    T[x].sum = T[c0].sum + T[c1].sum + T[x].v;
    T[x].lmax = max(T[c0].lmax, T[c0].sum + T[x].v + max(T[c1].lmax, 0));
    T[x].rmax = max(T[c1].rmax, max(T[c0].rmax, 0) + T[x].v + T[c1].sum);
    T[x].midmax = max(T[c0].midmax, T[c1].midmax, max(T[c0].rmax, 0) + T[x].v + max(T[c1].lmax, 0));
}

void rot(int x)
{
    int y = T[x].p;
    bool d = T[x].d;
    if(y == root)
    {
        root = x;
        T[root].p = 0;
    }
    else  sc(T[y].p, x, T[y].d);
    sc(y, T[x].c[!d], d);
    sc(x, y, !d);
    upd(y);
}

void splay(int x, int r)
{
    int p;
    while((p = T[x].p) != r)
    {
        if(T[p].p == r) rot(x);
        else
        {
            if(T[x].d == T[p].d)
            {
                rot(p);
                rot(x);
            }
            else
            {
                rot(x);
                rot(x);
            }
        }
    }
    upd(x);
}

void prepare()
{
    T[0].sz = T[0].sum =T[0].lmax = T[0].rmax = T[0].midmax = 0;

    front = 3;
    rear = MAXN;
    for(int i = 1; i <= MAXN; i++) Q[i] = i;

    newnode(1, -INF);
    newnode(2, -INF);

    sc(1, 2, 1);

    root = 1;
    T[root].p = 0;
}

int Find_kth(int k)
{
    int i = root ,s0;
    while(i)
    {
        dm(i);
        s0 = T[T[i].c[0]].sz + 1;
        if(s0 == k)  break;
        else if(k < s0)  i = T[i].c[0];
        else
        {
            k -= s0;
            i = T[i].c[1];
        }
    }
    return i;
}

int mkt(int l, int r)
{
    if(l > r)  return 0 ;

    int n0 = Q[front], mid = (l + r) >> 1;

    if(front == MAXN)  front  = 1;
    else front ++;

    newnode(n0, a[mid]);

    int l_r = mkt(l, mid - 1), r_r = mkt(mid + 1, r);

    sc(n0, l_r, 0);
    sc(n0, r_r, 1);

    upd(n0);
    return n0;
}

void ins(int x)
{
    int  p0 = Find_kth(x);
    splay(p0, 0);
    int p1 = Find_kth(x + 1);
    splay(p1, root);
    sc(p1, mkt(0, len - 1), 0);
    upd(p1);
    upd(p0);
}

void era(int x)
{
    if(!x)  return;
    if(rear == MAXN)  rear = 1;
    else rear ++;
    Q[rear] = x;
    era(T[x].c[0]);
    era(T[x].c[1]);
}

void del(int l, int r)
{
    int p0 = Find_kth(l - 1);
    splay(p0, 0);
    int p1 = Find_kth(r + 1);
    splay(p1, root);
    int root0 = T[p1].c[0];
    sc(p1, 0, 0);//_________
    upd(p1);
    upd(p0);
    era(root0);
}

void mksame(int l, int r, int x)
{
    int p0 = Find_kth(l - 1);
    splay(p0, 0);
    int p1 = Find_kth(r + 1);
    splay(p1, root);
    sm_opr(T[p1].c[0], x);
    upd(p1);
    upd(p0);
}

void reve(int l, int r)
{
    int p0 = Find_kth(l - 1);
    splay(p0, 0);
    int p1 = Find_kth(r + 1);
    splay(p1, root);
    rev_opr(T[p1].c[0]);
    upd(p1);
    upd(p0);
}

int get_sum(int l, int r)
{
    // printf("l=%d   r=%d\n", l, r);
    int P0 = Find_kth(l - 1);
    // printf("p0=%d\n",P0);
    splay(P0, 0);
    int P1 = Find_kth(r + 1);
    splay(P1, root);
    int n = T[P1].c[0];
    return T[n].sum;
}

int max_sum()
{
    return T[root].midmax;
}
int main()
{
    int TT;
    int m, l, r, x;
    char str[100];
    scanf("%d", &TT);
    while(TT--)
    {
        prepare();

        scanf("%d%d", &len, &m);
        for(int i = 0; i < len; i++)   scanf("%d", &a[i]);
        ins(1);
        for(int i = 0; i < m; i++)
        {
            scanf("%s", str);
            if (!strcmp(str, "INSERT"))
            {
                scanf("%d%d", &l, &len);
                for(int i = 0; i < len; i++)   scanf("%d", &a[i]);
                l++;
                ins(l);
            }
            if (!strcmp(str, "DELETE"))
            {
                scanf("%d%d", &l, &r);
                r += l;
                l++;
                del(l, r);
            }
            if (!strcmp(str, "MAKE-SAME"))
            {
                scanf("%d%d%d", &l, &r, &x);
                r += l;
                l++;
                mksame(l, r, x);
            }
            if (!strcmp(str, "REVERSE"))
            {
                scanf("%d%d", &l, &r);
                r += l;
                l++;
                reve(l, r);
            }
            if (!strcmp(str, "GET-SUM"))
            {
                scanf("%d%d", &l, &r);
                r += l;
                l++;
                printf("%d\n", get_sum(l, r));
            }
            if (!strcmp(str, "MAX-SUM")) printf("%d\n", max_sum());
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值