关闭

[BZOJ1500][NOI2005]维修数列

标签: splay
158人阅读 评论(0) 收藏 举报
分类:

[NOI2005]维修数列

Description
这里写图片描述

Input
输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。
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
Source
Splay

Solution :
半条命。

Code :

#include <bits/stdc++.h>
using namespace std;

#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define REP(i, n) for (int i = 0; i < (n); i++)
#define PER(i, n) for (int i = (n)-1; i >= 0; i--)
#define stack _stack
const int INF = ~0U>>2;
const int N = 555555;

template<typename T> inline void read(T &x){
    x = 0; T f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch))  {x = x * 10 + ch - '0'; ch = getchar();}
    x *= f;
}
template<typename T> inline void write(T x){
    static T a[20]; int ptr = 0;
    if (!x) { puts("0"); return; }
    if (x < 0) { putchar('-'); x = -x; }
    while (x) a[ptr++] = x % 10, x /= 10;
    per(i, ptr-1, 0) putchar('0' + a[i]);
    putchar('\n');
}

struct info{
    int lmx, rmx, sum, mx, val, sz;
    void mark_same(int t){
        sum = t * sz; val = t; lmx = rmx = mx = max(sum, t);
    }
    void mark_rev() { swap(lmx, rmx); }
    void set_one(int t) { sz = 1; mark_same(t); }
};
inline void merge_info(info &F, const info &L, const info &R){
    F.sz = L.sz + R.sz + 1;
    F.sum = L.sum + R.sum + F.val;
    int LL = max(0, L.rmx), RR = max(0, R.lmx);
    F.lmx = max(L.lmx, L.sum + F.val + RR);
    F.rmx = max(R.rmx, R.sum + F.val + LL);
    F.mx = max(LL + F.val + RR, max(L.mx, R.mx));
}
struct mark{
    bool rev, is_same; int same;
    void mark_same(int t){ same = t; is_same = 1; }
    void mark_rev(){ rev ^= 1; }
    void clear(){ is_same = rev = false; }
};
struct node{
    node *p, *c[2]; info I; mark M;
    bool d(){ return p->c[1] == this; }
    void sc(node *_c, bool _d) {c[_d] = _c; _c->p = this;}
}*Null, *root;
inline void mark_same(node *t, int same){ if (t == Null) return;
    t->M.mark_same(same); t->I.mark_same(same);
}
inline void mark_rev(node *t){ if (t == Null) return;
    t->M.mark_rev(); t->I.mark_rev(); swap(t->c[0], t->c[1]);
}

node mem[N];
node *stack[N]; int top;
int n, m, A[N];
char opt[N];

inline void init_memory(){ REP(i, N) stack[i] = mem + i; top = N; }
inline node *new_node(){ return stack[--top]; }
inline node *new_node(int val){
    node *ret = new_node();
    ret->I.set_one(val);
    ret->c[0] = ret->c[1] = ret->p = Null;
    ret->M.clear();
    return ret;
}
inline void delete_node(node *t) { stack[top++] = t; }
inline void init_null(){
    Null = new_node(-INF);
    Null->I.sz = Null->I.sum = 0;
    Null->c[0] = Null->c[1] = Null->p = Null;
}
inline void sweep(node *t_root){
    static node *q[N];
    static int head, tail;
    for (q[head = tail = 0] = t_root; head <= tail; head++){
        node *x = q[head];
        if (x->c[0] != Null) q[++tail] = x->c[0];
        if (x->c[1] != Null) q[++tail] = x->c[1];
        delete_node(x);
    }
}

inline void push_down(node *t){ if (t == Null) return;
    mark &m = t->M;
    if (m.is_same){
        mark_same(t->c[0], m.same); mark_same(t->c[1], m.same);
        m.is_same = false;
    }
    if (m.rev){mark_rev(t->c[0]); mark_rev(t->c[1]); m.rev ^= 1;}
}
inline void push_up(node *t){ if (t == Null) return;
    merge_info(t->I, t->c[0]->I, t->c[1]->I);
}
inline void rotate(node *t){
    node *p = t->p; bool d = t->d(); push_down(p); push_down(t);
    p->sc(t->c[!d], d);
    if (p-p == Null) t->p = Null; else p->p->sc(t, p->d());
    t->sc(p, !d); push_up(p);
    if (p == root) root = t;
}
inline void splay(node *t, node *f){
    for(push_down(t); t->p != f;){
        if (t->p->p == f) rotate(t);
        else t->d() == t->p->d() ? 
             (rotate(t->p), rotate(t)): (rotate(t), rotate(t));
    }
    push_up(t);
}
inline node *make_tree(int *l, int *r){
    if (l >= r) return Null;
    if (l + 1 == r) { return new_node(*l); }
    int *mid = l+(r-l)/2;
    node *t = new_node(*mid);
    t->sc(make_tree(l, mid), 0); t->sc(make_tree(mid+1, r), 1);
    push_up(t);
    return t;
}
inline node *find(int k){
    for(node *t = root; ;){push_down(t);
        int cnt = t->c[0]->I.sz;
        if (cnt == k) return t;
        t = t->c[k>cnt];
        if (k>cnt) k -= cnt+1;
    }
}
node *&getseq(int l, int r){
    node *L = find(l); splay(L, Null);
    node *R = find(r); splay(R, root);
    return root->c[1]->c[0];
}

inline void build(){
    init_memory(); init_null(); root = new_node(-INF + 1);
    node *End = new_node(-INF + 1);
    root->sc(End, 1);
    splay(End, Null);
}
inline void _insert(int tot, int pos){
    REP(i, tot) read(A[i]);
    node *t_root = make_tree(A, A+tot); 
    getseq(pos, pos+1);
    root->c[1]->sc(t_root, 0);
    splay(t_root, Null);
}
inline void _delete(int tot, int pos){
    node *t_root = getseq(pos - 1, pos + tot);
    t_root->p->sc(Null, 0);
    splay(root->c[1], Null);
    sweep(t_root);
}
inline void _reverse(int tot, int pos){
    node *t_root = getseq(pos - 1, pos + tot);
    mark_rev(t_root);
    splay(t_root, Null);
}
inline void _modify(int tot, int pos, int val){
    node *t_root = getseq(pos - 1, pos + tot);
    mark_same(t_root, val);
    splay(t_root, Null);
}
inline void _calc_sum(int tot, int pos){
    node *t_root = getseq(pos - 1, pos + tot);
    write(t_root->I.sum);
}
inline void _calc_max(){ write(root->I.mx); }

inline void solve(){
    read(n); read(m); build();
    _insert(n, 0); int tot, pos, val;
    while (m--){
        scanf("%s", opt);
        switch(opt[0]){
            case 'I': read(pos); read(tot); _insert(tot, pos); OK break;
            case 'D': read(pos); read(tot); _delete(tot, pos); OK break;
            case 'R': read(pos); read(tot); _reverse(tot, pos); OK break;
            case 'G': read(pos); read(tot); _calc_sum(tot, pos); OK break;
            case 'M':
                if (opt[2] == 'X') _calc_max();
                else{
                    read(pos); read(tot); read(val); _modify(tot, pos, val);
                } OK
                break;
        }
    }
}
int main(){
    solve(); return 0;
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:40836次
    • 积分:1402
    • 等级:
    • 排名:千里之外
    • 原创:99篇
    • 转载:3篇
    • 译文:0篇
    • 评论:6条
    友情链接