洛谷P2042 [NOI2005]维护数列
? 解题记录 ? ? 洛谷 ? ? Splay ? ? 平衡树 ?    2018-01-16 08:01:32    394    0    0

题目描述

请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格)

输入输出格式

输入格式:

 

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

 

输出格式:

 

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

 

输入输出样例

输入样例#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
输出样例#1: 复制
-1
10
1
10

说明

你可以认为在任何时刻,数列中至少有 1 个数。

输入数据一定是正确的,即指定位置的数在数列中一定存在。

50%的数据中,任何时刻数列中最多含有 30 000 个数;

100%的数据中,任何时刻数列中最多含有 500 000 个数。

100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。

100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 。

平衡树裸题,就是写的有点蛋疼……维护和最大的一串的话,就按基本套路。左端点开始的最大,右端点开始的最大中间的最大。每一次查询root就可以了。

#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 5e5 + 5;
const int inf = 0x3f3f3f3f >> 1;
char s[10];
namespace Splay {
    const int L = 0, R = 1;
    struct node {
        int ch[2], size, num, fa;
        int sum, edit, rev, Lmax, Rmax, Mmax;
    }tree[maxn];
    queue<int > Mempool;
    int root, cnt, null;
    int Newnode() {
    	if(Mempool.empty()) return ++cnt;
    	null = Mempool.front(); Mempool.pop();
    	return tree[null] = (node){}, tree[null].edit = -inf, null;
   	}
    void push_up(int rt) {
    	int tl = tree[rt].ch[L], tr = tree[rt].ch[R];
        tree[rt].sum = tree[tl].sum + tree[tr].sum + tree[rt].num;
        tree[rt].Lmax = max(tree[tl].sum + tree[rt].num + tree[tr].Lmax, tree[tl].Lmax);
        tree[rt].Rmax = max(tree[tr].sum + tree[rt].num + tree[tl].Rmax, tree[tr].Rmax);
        tree[rt].Mmax = max(max(tree[tl].Mmax, tree[tr].Mmax), tree[tl].Rmax + tree[rt].num + tree[tr].Lmax);
        tree[rt].size = tree[tl].size + tree[tr].size + 1;
    }
    void push_down(int rt) {
    	int tl = tree[rt].ch[L], tr = tree[rt].ch[R];
    	if(tree[rt].edit >= -100000) {
    		int w = tree[rt].edit, sz = tree[rt].size;
    		tree[tl].edit = tree[tl].num = tree[tr].edit = tree[tr].num = w;
    		tree[rt].rev = tree[tl].rev = tree[tr].rev = 0;
    		tree[tl].sum = w * tree[tl].size, tree[tr].sum = w * tree[tr].size;
    		if(tl) {
        		tree[tl].Lmax = tree[tl].Rmax = max(tree[tl].sum, 0);
        		tree[tl].Mmax = max(tree[tl].sum, w);
        	}
        	if(tr) {
        		tree[tr].Lmax = tree[tr].Rmax = max(tree[tr].sum, 0);
        		tree[tr].Mmax = max(tree[tr].sum, w);
        	}
            tree[rt].edit = -inf;
        } else if(tree[rt].rev) {
            tree[tl].rev ^= 1, tree[tr].rev ^= 1;
            swap(tree[rt].ch[L], tree[rt].ch[R]);
            swap(tree[tl].Lmax, tree[tl].Rmax);
            swap(tree[tr].Lmax, tree[tr].Rmax);
            tree[rt].rev = 0;
        }
    }
    void recyc(int rt) {
    	Mempool.push(rt);
    	if(tree[rt].ch[L]) recyc(tree[rt].ch[L]);
    	if(tree[rt].ch[R]) recyc(tree[rt].ch[R]);
    } 
    void rotate(int rt) {
        int p = tree[rt].fa, a = tree[p].fa;
        int r = tree[p].ch[R] == rt, l = r ^ 1;
        if(a) tree[a].ch[tree[a].ch[R] == p] = rt;
        tree[rt].fa = a, tree[p].fa = rt, tree[tree[rt].ch[l]].fa = p;
        tree[p].ch[r] = tree[rt].ch[l], tree[rt].ch[l] = p;
        push_up(p), push_up(rt);
    }
    void splay(int rt, int y) {
        int des = tree[y].fa;
        while(tree[rt].fa != des) {
            int p = tree[rt].fa, a = tree[p].fa;
            push_down(p), push_down(rt);
            if(p != y) {
                if((tree[a].ch[R] == p) ^ (tree[p].ch[R] == rt)) rotate(rt);
                else rotate(p);
            }
            rotate(rt);
        }
        if(y == root) root = rt;
        push_up(rt);
    }
    int qnode(int rank) {
        int now = root;
        ++rank, push_down(now);
        for(int tl = tree[now].ch[L]; now; push_down(now), tl = tree[now].ch[L]) {
            if(rank <= tree[tl].size) now = tl;
            else if(rank > tree[tl].size + 1)
                rank -= tree[tl].size + 1, now = tree[now].ch[R];
            else return now;
        }
        return now;
    }
    void Rev(int l, int r) {
        int ls = qnode(l - 1), rs = qnode(r + 1), rt;
        splay(ls, root), splay(rs, tree[ls].ch[R]);
        tree[rt = tree[rs].ch[L]].rev ^= 1;
        swap(tree[rt].Lmax, tree[rt].Rmax);
        push_up(rs), push_up(ls);
    }
    void build(int & rt, int l, int r, int last, int * arr) {
    	int mid = l + r >> 1, w = arr[mid];
    	rt = Newnode();
    	if(l == r) {
    		tree[rt].size = 1;
    		tree[rt].rev = 0, tree[rt].sum = w;
        }
        tree[rt].Lmax = tree[rt].Rmax = max(w, 0);
        tree[rt].Mmax = w, tree[rt].edit = -inf;
    	tree[rt].num = w, tree[rt].fa = last;     	
        if(l < mid) build(tree[rt].ch[L], l, mid - 1, rt, arr);
    	if(r > mid) build(tree[rt].ch[R], mid + 1, r, rt, arr);
    	if(tree[rt].size != 1) push_up(rt);
    }
    void Ins(int n, int pos, int * arr) {
    	if(!n) return;
    	int pr = qnode(pos), su = qnode(pos + 1);
    	splay(pr, root), splay(su, tree[root].ch[R]);
    	build(tree[su].ch[L], 1, n, su, arr);
    	push_up(su), push_up(pr);
    }
    void Del(int pos, int len) {
    	if(!len) return;
    	int pr = qnode(pos - 1), su = qnode(pos + len);
    	splay(pr, root), splay(su, tree[root].ch[R]), recyc(tree[su].ch[L]);
    	tree[su].ch[L] = 0, push_up(su), push_up(pr);
    }
    void Edit(int pos, int len, int w) {
    	if(!len) return;
    	int pr = qnode(pos - 1), su = qnode(pos + len);
    	splay(pr, root), splay(su, tree[root].ch[R]);
    	int now = tree[su].ch[L];
    	tree[now].edit = tree[now].num = w;
    	tree[now].sum = tree[now].size * w;
    	tree[now].Lmax = tree[now].Rmax = max(tree[now].sum, 0);
    	tree[now].Mmax = max(tree[now].sum, w); 
    	push_up(su), push_up(pr);
    }
    int GetSum(int pos, int len) {
    	if(!len) return 0;
    	int pr = qnode(pos - 1), su = qnode(pos + len);
    	splay(pr, root), splay(su, tree[root].ch[R]);
    	return tree[tree[su].ch[L]].sum;
    }
}
int n, m, u, v, arr[maxn], a, b, c;
int main() {
    using namespace Splay;
    scanf("%d%d", &n, &m);
    tree[0].Mmax = arr[0] = arr[n + 1] = -inf;
    tree[0].Mmax = -inf;
    for(register int i = 1; i <= n; ++i) scanf("%d", &arr[i]);
    build(root, 0, n + 1, 0, arr);
    while(m--) {
    	scanf("%s", s);
    	if(s[2] == 'X') {
    		printf("%d\n", tree[root].Mmax);
    	} else {
    		scanf("%d%d", &a, &b);
    		if(s[2] == 'S') {
        		for(register int i = 1; i <= b; ++i) scanf("%d", &arr[i]);
        		Ins(b, a, arr);
            } else if(s[2] == 'L') Del(a, b);
            else if(s[2] == 'K') scanf("%d", &c), Edit(a, b, c);
            else if(s[2] == 'V') Rev(a, a + b - 1);
            else if(s[2] == 'T') printf("%d\n", GetSum(a, b));
        }
    }
    return 0;
}

 

上一篇: 洛谷P3181 [HAOI2016]找相同字符

下一篇: BZOJ4942:[Noi2017]整数

394 人读过
立即登录, 发表评论.
没有帐号? 立即注册
0 条评论
文档导航