BZOJ 1500: [NOI2005] 维修数列

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


传说中巨变态的一道题。。。调了一下午终于AC了。。。模板:Orz神犇黄学长 @hzwer

血的教训:

边界值一定要初始化!边界值一定要初始化!边界值一定要初始化!重要的事情说三遍!

放代码:

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

const int MAXN = 1000005, INF = 0x3f3f3f3f;
int N, M, root, spa[MAXN], top, A[MAXN], id[MAXN], tot;
int rd(){
	int x=0, f=0, ch = getchar();
	while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();};
	while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();};
	return f?-x:x;
}
struct SplayTree{
	int fa[MAXN], ch[MAXN][2];
	int v[MAXN], sz[MAXN], sum[MAXN], lx[MAXN], rx[MAXN], mx[MAXN];	
	int cov[MAXN], rev[MAXN];
	
	void trace(){
		printf("root=%d, tot=%d\n", root, tot);
		for(int i = 0; i <= N+2; ++i){
			printf("%d: ", i);
			printf("fa=%d, ch[0]=%d, ch[1]=%d, v=%d, sz=%d,\n",
			fa[i], ch[i][0], ch[i][1], v[i], sz[i]);
			printf("sum=%d, lx=%d, rx=%d, mx=%d, cov=%d, rev=%d;\n",
			sum[i], lx[i], rx[i], mx[i], cov[i], rev[i]);
		}
	}
	void dfs(int x){
		if(x == 0) return;
		dfs(ch[x][0]);
		if(v[x] != -INF)printf("%d ", v[x]);
		dfs(ch[x][1]);
	}
	void pushup(int x){
		int l = ch[x][0], r = ch[x][1];
		sz[x] = 1 + sz[l] + sz[r];
		sum[x] = v[x] + sum[l] + sum[r];
		lx[x] = max(lx[l], sum[l] + v[x] + lx[r]);
		rx[x] = max(rx[r], sum[r] + v[x] + rx[l]);
		mx[x] = max(rx[l] + v[x] + lx[r], max(mx[l], mx[r]));
	}
	void pushdown(int x){
		int l = ch[x][0], r = ch[x][1];
		if(cov[x] != INF){
			if(l){
				v[l] = cov[x];
				sum[l] = sz[l] * cov[x];
				lx[l] = rx[l] = cov[x] > 0 ? sum[l] : 0;
				mx[l] = cov[x] > 0 ? sum[l] : cov[x];
				cov[l] = cov[x]; rev[l] = 0;
			}
			if(r){
				v[r] = cov[x];
				sum[r] = sz[r] * cov[x];
				lx[r] = rx[r] = cov[x] > 0 ? sum[r] : 0;
				mx[r] = cov[x] > 0 ? sum[r] : cov[x];
				cov[r] = cov[x]; rev[r] = 0;
			}
			cov[x] = INF; rev[x] = 0;
		}
		else if(rev[x]){
			rev[l] ^= 1; rev[r] ^= 1; rev[x] = 0;
			swap(lx[l], rx[l]); swap(lx[r], rx[r]);
			swap(ch[l][0], ch[l][1]); swap(ch[r][0], ch[r][1]);
		}
	}
	void rot(int x, int &k){
		int y = fa[x], z = fa[y], l = ch[y][1] == x, r = l ^ 1;
		if(y == k) k = x;
		else ch[z][ch[z][1] == y] = x;
		fa[ch[x][r]] = y; fa[y] = x; fa[x] = z;
		ch[y][l] = ch[x][r]; ch[x][r] = y;
		pushup(y); pushup(x);
	}
	void splay(int x, int &k){
		while(x != k){
			int y = fa[x], z = fa[y];
			if(y != k){
				if((ch[y][1] == x) ^ (ch[z][1] == y)) rot(x, k);
				else rot(y, k);
			}
			rot(x, k);
		}
	}
	int srch(int x, int k){
		pushdown(x);
		int l = ch[x][0], r = ch[x][1];
		if(k == sz[l] + 1) return x;
		if(k <= sz[l]) return srch(l, k);
		return srch(r, k - sz[l] - 1);
	}
	int &split(int k, int t){
		int x = srch(root, k), y = srch(root, k + t + 1);
		splay(x, root); splay(y, ch[x][1]);
		return ch[y][0];
	}
	void build(int &x, int f, int L, int R){
		if(L > R) return;
		if(L == R){
			x = id[L]; fa[x] = f; v[x] = sum[x] = mx[x] = A[L];
			sz[x] = 1; cov[x] = INF; rev[x] = 0;
			if(A[L] > 0) lx[x] = rx[x] = A[L];
			else lx[x] = rx[x] = 0;
			return;
		}
		int mid = (L + R) >> 1;
		x = id[mid]; fa[x] = f; v[x] = A[mid]; cov[x] = INF; rev[x] = 0;
		build(ch[x][0], x, L, mid-1);
		build(ch[x][1], x, mid+1, R);
		pushup(x);
	}
	void ins(){
		int k = rd(), t = rd(), x, y;
		for(int i = 1; i <= t; ++i){
			A[i] = rd();
			id[i] = top ? spa[--top] : ++tot; 
		}
		x = srch(root, k+1), y = srch(root, k+2);
		splay(x, root); splay(y, ch[x][1]);
		build(ch[y][0], y, 1, t);
		pushup(y); pushup(x);
	}
	void rec(int x){
		if(!x) return;
		rec(ch[x][0]); rec(ch[x][1]); 
		fa[x] = ch[x][0] = ch[x][1] = 0;
		cov[x] = INF; rev[x] = 0;
		spa[top++] = x;
	}
	void del(){
		int k = rd(), t = rd();
		int &x = split(k, t), y = fa[x];
		rec(x); x = 0;
		pushup(y); pushup(fa[y]);
	}
	void modify(){
		int k = rd(), t = rd(), c = rd();
		int &x = split(k, t), y = fa[x];
		cov[x] = v[x] = c; sum[x] = c * sz[x]; rev[x] = 0;
		if(c < 0){
			lx[x] = rx[x] = 0; mx[x] = c;
		}else{
			lx[x] = rx[x] = mx[x] = sum[x];
		}
		pushup(y); pushup(fa[y]);
	}
	void rever(){
		int k = rd(), t = rd();
		int x = split(k, t), y = fa[x];
		rev[x] ^= 1;
		swap(ch[x][0], ch[x][1]);
		swap(lx[x], rx[x]);
		pushup(y); pushup(fa[y]);
	}
	void gsum(){
		int k = rd(), t = rd();
		if(t == 0){printf("0\n"); return; }
		int x = split(k, t);
		printf("%d\n", sum[x]);
	}
	void gmax(){
		printf("%d\n", mx[root]);
	}
}spt;

char opt[128];
int main(){
	freopen("sequence9.in", "r", stdin);
	freopen("my.txt", "w", stdout);
	scanf("%d%d", &N, &M);
	for(int i = 2; i <= N + 1; ++i){
		A[i] = rd(); id[i] = ++tot;
	}
	spt.mx[0] = A[1] = A[N+2] = -INF; id[1] = ++tot; id[N+2] = ++tot;	//重要! 
	spt.build(root, 0, 1, N+2);
	memset(spt.cov, 0x3f, sizeof(spt.cov));
	for(int i = 1; i <= M; ++i){
//		spt.trace();
//		spt.dfs(root); putchar('\n');
		scanf("%s", opt);
//		printf("%d: %s %d\n", i, opt, spt.sz[root]);
		switch(opt[0]){
			case 'I':
				spt.ins();
				break;
			case 'D':
				spt.del();
				break;
			case 'R':
				spt.rever();
				break;
			case 'G':
				spt.gsum();
				break;
			case 'M':
				if(opt[2] == 'K'){
					spt.modify();
				}else{
					spt.gmax();
				}
				break;
		}
	}
	return 0;
}


posted @ 2016-04-09 23:21  will7101  阅读(134)  评论(0编辑  收藏  举报