bzoj1500: [NOI2005]维修数列

3 篇文章 0 订阅

Description
这里写图片描述

Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

Sample Input
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

Sample Output
-1
10
1
10

HINT
这里写图片描述

好好想想吧.. 这道题就是splay很多操作的题目.. 就是很难调很难打而已..

记住要初始化啊.. 我错了一天..

怒敲150+行..

#include <cstdio> 
#include <cstring> 
#include <cstdlib> 
#include <algorithm> 
using namespace std; 
const int Maxn = 500010; 
int ls[Maxn], rs[Maxn], ms[Maxn], id[Maxn], tp, sum[Maxn], fa[Maxn], size[Maxn], rev[Maxn], c[Maxn][2]; 
bool tag[Maxn]; 
int n, m; 
int a[Maxn], rt, val[Maxn]; 
int _max ( int x, int y ){ return x > y ? x : y; } 
void push_down ( int now ){ 
    if ( now == 0 ) return; 
    int lc = c[now][0], rc = c[now][1]; 
    if ( tag[now] ){ 
        if ( val[now] > 0 ){ 
            if ( lc > 0 ){ 
                val[lc] = val[now]; 
                ls[lc] = rs[lc] = ms[lc] = sum[lc] = val[now]*size[lc]; 
                tag[lc] = 1; 
            } 
            if ( rc > 0 ){ 
                val[rc] = val[now]; 
                ls[rc] = rs[rc] = ms[rc] = sum[rc] = val[now]*size[rc]; 
                tag[rc] = 1; 
            } 
        } 
        else { 
            if ( lc > 0 ){ 
                val[lc] = val[now]; 
                sum[lc] = val[now]*size[lc]; 
                ls[lc] = rs[lc] = 0; ms[lc] = val[now]; 
                tag[lc] = 1; 
            } 
            if ( rc > 0 ){ 
                val[rc] = val[now]; 
                sum[rc] = val[now]*size[rc]; 
                ls[rc] = rs[rc] = 0; ms[rc] = val[now]; 
                tag[rc] = 1; 
            } 
        } 
        tag[now] = 0; rev[now] = 0; 
    } 
    if ( rev[now] ){ 
        rev[now] = 0; 
        rev[lc] ^= 1; rev[rc] ^= 1; 
        swap ( ls[lc], rs[lc] ); swap ( ls[rc], rs[rc] ); 
        swap ( c[lc][0], c[lc][1] ); swap ( c[rc][0], c[rc][1] ); 
    } 
} 
void update ( int now ){ 
    int lc = c[now][0], rc = c[now][1]; 
    ls[now] = _max ( ls[lc], sum[lc]+val[now]+ls[rc] ); 
    rs[now] = _max ( rs[rc], sum[rc]+val[now]+rs[lc] ); 
    size[now] = size[lc]+size[rc]+1; 
    sum[now] = sum[lc]+sum[rc]+val[now]; 
    ms[now] = _max ( ms[lc], _max ( ms[rc], ls[rc]+val[now]+rs[lc] ) ); 
} 
void clear ( int now ){ tag[now] = 0; val[now] = rev[now] = c[now][0] = c[now][1] = 0; } 
void bulid ( int &now, int l, int r, int f ){ 
    if ( l > r ){ now = 0; return; } 
    now = id[++tp]; 
    clear (now); 
    if ( l == r ){ 
        fa[now] = f; 
        if ( a[l] > 0 ) ls[now] = rs[now] = ms[now] = a[l]; 
        else { ls[now] = rs[now] = 0; ms[now] = a[l]; } 
        sum[now] = val[now] = a[l]; 
        size[now] = 1; 
        return; 
    } 
    fa[now] = f; 
    int mid = ( l + r ) >> 1; 
    val[now] = a[mid]; 
    bulid ( c[now][0], l, mid-1, now ); 
    bulid ( c[now][1], mid+1, r, now ); 
    update (now); 
} 
void del ( int now ){ 
    if ( now == 0 ) return; 
    id[tp--] = now; 
    del (c[now][0]); del (c[now][1]); 
} 
void rotate ( int x, int &k ){ 
    int y = fa[x], z = fa[y], l, r; 
    if ( c[y][0] == x ) l = 0; else l = 1; r = l^1; 
    if ( y == k ) k = x; 
    else { if ( c[z][0] == y ) c[z][0] = x; else c[z][1] = x; } 
    fa[x] = z; fa[y] = x; fa[c[x][r]] = y; 
    c[y][l] = c[x][r]; c[x][r] = y; 
    update (y); update (x); 
} 
void splay ( int x, int &k ){ 
    while ( x != k ){ 
        int y = fa[x], z = fa[y]; 
        if ( y != k ){ 
            if ( (c[y][0]==x)^(c[z][0]==y) ) rotate ( x, k ); 
            else rotate ( y, k ); 
        } 
        rotate ( x, k ); 
    } 
} 
int find ( int now, int rank ){ 
    push_down (now); 
    int lc = c[now][0], rc = c[now][1]; 
    if ( rank == size[lc]+1 ) return now; 
    else if ( rank <= size[lc] ) return find ( lc, rank ); 
    else return find ( rc, rank-size[lc]-1 ); 
} 
char s[11]; 
int main (){ 
    int i, j, k; 
    for ( i = 1; i <= 500005; i ++ ) id[i] = i; 
    ms[0] = -1e9; 
    tp = 0; 
    scanf ( "%d%d", &n, &m ); 
    for ( i = 2; i <= n+1; i ++ ) scanf ( "%d", &a[i] ); 
    a[1] = a[n+2] = -1e9; 
    bulid ( rt, 1, n+2, 0 ); 
    for ( i = 1; i <= m; i ++ ){ 
        getchar (); 
        scanf ( "%s", s+1 ); 
        if ( s[1] == 'I' ){ 
            int x, tot; 
            scanf ( "%d%d", &x, &tot ); 
            for ( j = 1; j <= tot; j ++ ) scanf ( "%d", &a[j] ); 
            int p1 = find ( rt, x+1 ); 
            int p2 = find ( rt, x+2 ); 
            splay ( p1, rt ); 
            splay ( p2, c[p1][1] ); 
            push_down (p1); push_down (p2); 
            bulid ( c[p2][0], 1, tot, p2 ); 
            update (p2); update (p1); 
        } 
        else if ( s[1] == 'D' ){ 
            int x, tot; 
            scanf ( "%d%d", &x, &tot ); 
            int p1 = find ( rt, x ); 
            int p2 = find ( rt, x+tot+1 ); 
            splay ( p1, rt ); 
            splay ( p2, c[p1][1] ); 
            del (c[p2][0]); 
            c[p2][0] = 0; 
            update (p2); update (p1); 
        } 
        else if ( s[1] == 'M' && s[3] == 'K' ){ 
            int x, tot, cc; 
            scanf ( "%d%d%d", &x, &tot, &cc ); 
            int p1 = find ( rt, x ); 
            int p2 = find ( rt, x+tot+1 ); 
            splay ( p1, rt ); 
            splay ( p2, c[p1][1] ); 
            tag[c[p2][0]] = 1; val[c[p2][0]] = cc; 
            sum[c[p2][0]] = cc*size[c[p2][0]]; 
            if ( cc > 0 ) ls[c[p2][0]] = rs[c[p2][0]] = ms[c[p2][0]] = sum[c[p2][0]]; 
            else { ls[c[p2][0]] = rs[c[p2][0]] = 0; ms[c[p2][0]] = cc; } 
            update (p2); update (p1); 
        } 
        else if ( s[1] == 'R' ){ 
            int x, tot; 
            scanf ( "%d%d", &x, &tot ); 
            int p1 = find ( rt, x ); 
            int p2 = find ( rt, x+tot+1 ); 
            splay ( p1, rt ); 
            splay ( p2, c[p1][1] ); 
            if ( tag[c[p2][0]] == 0 ){ 
                rev[c[p2][0]] ^= 1; 
                swap ( c[c[p2][0]][0], c[c[p2][0]][1] ); 
                swap ( ls[c[p2][0]], rs[c[p2][0]] ); 
                update (p2); update (p1); 
            } 
        } 
        else if ( s[1] == 'G' ){ 
            int x, tot; 
            scanf ( "%d%d", &x, &tot ); 
            int p1 = find ( rt, x ); 
            int p2 = find ( rt, x+tot+1 ); 
            splay ( p1, rt ); 
            splay ( p2, c[p1][1] ); 
            printf ( "%d\n", sum[c[p2][0]] ); 
        } 
        else printf ( "%d\n", ms[rt] ); 
    } 
    return 0; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值