[置顶] hdu 4699 2个栈维护 or 伸展树

hdu 4699  Editor

题意:对一个数列进行操作,光标位置后面插入一个权值为x的数,删除光标前的那个数,光标左移一位,光标右移一位,求到k位置的最大的前缀和。。

注意这里的k是在光标之前的,由于这个条件,所以这题又简单的2个栈维护可以解,如果没有这个条件,那么就要用伸展树了。

栈的解法叉姐的解题报告有,我这里说说伸展树的做法, 1.8MS卡过。

我们用cur表示光标在第几个数的右边,size表示数的总个数。

对于操作L: 没有移到最左边就cur--

对于操作R: 没有移到最右边就cur++

对于操作D: 把当前的第cur个位置的节点旋到根,再把第cur-1位置的节点旋到根的左边,令根的左右儿子分别为L,R

那么L一定没有右儿子,把L变为根, R变为L的右儿子。

对于操作I x:把当前的第cur个位置的节点旋到根,在根和根的右儿子之间插入一个新节点。

对于操作Q x:相当于询问1------x区间的最大前缀和。把第0个节点旋到根,把第x-1个节点旋到根的右边。

如何求最大前缀和, 维护一个sum[x]表示区间和,ans[x]表示在x为根的区间里的最大前缀和(注意至少要取一个数)。

伸展树:

 

#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 1000006;
using namespace std;
#define L ch[x][0]
#define R ch[x][1]
#define KT ch[ ch[root][1]][0]
int cur, size;
struct splaytree {
	int sz[maxn], ch[maxn][2], pre[maxn];
	int tot, root;
	int sum[maxn], val[maxn], ans[maxn];
	int sta[maxn], top;

	void rotate(int &x, int f) {
		int y = pre[x], z = pre[y];
		ch[y][!f] = ch[x][f];
		pre[ch[x][f]] = y;
		pre[x] = pre[y];
		if(z) ch[z][ch[z][1] == y] = x;
		ch[x][f] = y;
		pre[y] = x;
		up(y);
	}
	void splay(int &x, int g) {
		while(pre[x] != g) {
			int y = pre[x], z = pre[y];
			if(z == g) rotate(x, ch[y][0] == x);
			else {
				int f = (ch[z][0] == y);
				ch[y][!f] == x ? rotate(y, f) : rotate(x, !f);
				rotate(x, f);
			}
		}
		if(!g) root = x;
		up(x);
	}
	void rto(int k, int g) {
		int x = root;
		while(sz[L] != k) {
			if(sz[L] > k) x = L;
			else {
				k -= sz[L]+1;
				x = R;
			}
		}

		splay(x, g);
	}
	void newNode(int &x, int v, int fa) {
		if(top) x = sta[top--];
		else x = ++tot;
		sz[x] = 1;
		pre[x] = fa;
		L = R = 0;
		sum[x] = ans[x] = val[x] = v;
	}
	void init() {
		top = tot = 0;
		cur = size = 0;
		newNode(root, 0, 0);
		newNode(ch[root][1], 0, root);
	}
	void insert(int k, int v) {
		rto(k, 0);
//debug();
		int x;
		newNode(x, v, root);
		ch[x][1] = ch[root][1];
		pre[ch[x][1]] = x;
		ch[root][1] = x;
		up(x);
		up(root);
	}
	void erase(int k) {
		rto(k, 0);
		rto(k-1, root);
		sta[++top] = root;
		int l = ch[root][0], r = ch[root][1];
		root = l;
		pre[l] = 0;
		ch[l][1] = r;
		pre[r] = l;
		up(l);
	}
	void query(int k) {
		rto(0, 0);
		rto(k+1, root);
		printf("%d\n", ans[KT]);
	}
	void up(int x) {
		sz[x] = sz[L] + sz[R] + 1;
		sum[x] = sum[L] + sum[R] + val[x];
		ans[x] = max(ans[L], sum[L] + max(val[x], 0));
		ans[x] = max(ans[x], sum[L]+ val[x]+max(0, ans[R]));
	}
	void print(int x) {

		printf("node %d, left %d, right %d, pre %d, sum %d, ans %d, val %d\n", x, L, R, pre[x], sum[x], ans[x], val[x]);
        if(L) print(L);
		if(R) print(R);
	}
	void debug() {
	    printf("root = %d cur = %d\n", root, cur);
		print(root);
	}
	void down(int x) {

	}
}spt;
int main() {
	int m, x;
	char op[3];
	while( ~scanf("%d", &m)) {
		spt.init();

		while(m--) {
			scanf("%s", op);
			if(op[0] == 'L') {
                if(cur)cur--;
			}
			else if(op[0] == 'R') {
                if(cur < size)cur++;
			}
			else if(op[0] == 'D') spt.erase(cur--), size--;
			else {
				scanf("%d", &x);
				if(op[0] == 'I') spt.insert(cur++, x), size++;
				else spt.query(x);
			}
		//	spt.debug();
		}
	}
	return 0;
}


 

栈维护:

 

#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
const int maxn = 1000006;
int dp[maxn], sum[maxn], m, x;
const int inf =  1e9+6;
char op[3];
int l[maxn], r[maxn], t1, t2;
int main() {
    while( ~scanf("%d", &m)) {
        dp[0] = -inf;
        t1 = t2 = 0;
        while(m--) {
            scanf("%s", op);
            if(op[0] == 'I') {
                scanf("%d", &x);
                l[++t1] = x;
                sum[t1] = sum[t1-1] + x;
                dp[t1] = max(dp[t1-1], sum[t1]);
            }
            else if(op[0] == 'L') {
                if(!t1) continue;
                r[++t2] = l[t1--];
            }
            else if(op[0] == 'R') {
                if(!t2) continue;
                l[++t1] = r[t2--];
                sum[t1] = sum[t1-1] + l[t1];
                dp[t1] = max(dp[t1-1], sum[t1]);

            }
            else if(op[0] == 'D') t1--;
            else {
                scanf("%d", &x);
                printf("%d\n", dp[x]);
            }
        }

    }
    return 0;
}


 

 

posted on 2013-08-27 18:11  you Richer  阅读(160)  评论(0编辑  收藏  举报