【BZOJ1858】[Scoi2010]序列操作【线段树】

【题目链接】

调了一早上,码力++。


大概跪了几个地方:

pushdown里rx1手滑打成了rx0。

查询最大子段函数,区间合并忘了上传sum。

mx1合并时候直接写了赋值,忘了和原来的值取max。

/* Pigonometry */
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 100005, maxm = maxn << 2;

int n, m, sum[maxm], setv[maxm], xorv[maxm], lx0[maxm], rx0[maxm], mx0[maxm], lx1[maxm], rx1[maxm], mx1[maxm];

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

inline void pushup(int p, int l, int mid, int r) {
	sum[p] = sum[p << 1] + sum[p << 1 | 1];

	lx0[p] = lx0[p << 1];
	if(sum[p << 1] == 0) lx0[p] += lx0[p << 1 | 1];
	rx0[p] = rx0[p << 1 | 1];
	if(sum[p << 1 | 1] == 0) rx0[p] += rx0[p << 1];
	mx0[p] = max(max(mx0[p << 1], mx0[p << 1 | 1]), rx0[p << 1] + lx0[p << 1 | 1]);

	lx1[p] = lx1[p << 1];
	if(sum[p << 1] == mid - l + 1) lx1[p] += lx1[p << 1 | 1];
	rx1[p] = rx1[p << 1 | 1];
	if(sum[p << 1 | 1] == r - mid) rx1[p] += rx1[p << 1];
	mx1[p] = max(max(mx1[p << 1], mx1[p << 1 | 1]), rx1[p << 1] + lx1[p << 1 | 1]);
}

inline void pushdown(int p, int l, int mid, int r) {
	if(~setv[p]) {
		setv[p << 1] = setv[p << 1 | 1] = setv[p];
		xorv[p << 1] = xorv[p << 1 | 1] = 0;
		if(setv[p] == 0) {
			lx0[p << 1] = rx0[p << 1] = mx0[p << 1] = mid - l + 1;
			lx0[p << 1 | 1] = rx0[p << 1 | 1] = mx0[p << 1 | 1] = r - mid;
			lx1[p << 1] = rx1[p << 1] = mx1[p << 1] = 0;
			lx1[p << 1 | 1] = rx1[p << 1 | 1] = mx1[p << 1 | 1] = 0;
			sum[p << 1] = sum[p << 1 | 1] = 0;
		} else {
			lx0[p << 1] = rx0[p << 1] = mx0[p << 1] = 0;
			lx0[p << 1 | 1] = rx0[p << 1 | 1] = mx0[p << 1 | 1] = 0;
			lx1[p << 1] = rx1[p << 1] = mx1[p << 1] = mid - l + 1;
			lx1[p << 1 | 1] = rx1[p << 1 | 1] = mx1[p << 1 | 1] = r - mid;
			sum[p << 1] = mid - l + 1; sum[p << 1 | 1] = r - mid;
		}
		setv[p] = -1;
	}
	if(xorv[p]) {
		swap(lx0[p << 1], lx1[p << 1]); swap(rx0[p << 1], rx1[p << 1]);
		swap(mx0[p << 1], mx1[p << 1]); sum[p << 1] = mid - l + 1 - sum[p << 1];
		swap(lx0[p << 1 | 1], lx1[p << 1 | 1]); swap(rx0[p << 1 | 1], rx1[p << 1 | 1]);
		swap(mx0[p << 1 | 1], mx1[p << 1 | 1]); sum[p << 1 | 1] = r - mid - sum[p << 1 | 1];
		if(xorv[p << 1]) xorv[p << 1] = 0;
		else if(!~setv[p << 1]) xorv[p << 1] = 1;
		else if(setv[p << 1] == 0) setv[p << 1] = 1;
		else if(setv[p << 1] == 1) setv[p << 1] = 0;
		if(xorv[p << 1 | 1]) xorv[p << 1 | 1] = 0;
		else if(!~setv[p << 1 | 1]) xorv[p << 1 | 1] = 1;
		else if(setv[p << 1 | 1] == 0) setv[p << 1 | 1] = 1;
		else if(setv[p << 1 | 1] == 1) setv[p << 1 | 1] = 0;
		xorv[p] = 0;
	}
}

inline void build(int p, int l, int r) {
	sum[p] = xorv[p] = lx0[p] = rx0[p] = mx0[p] = lx1[p] = rx1[p] = mx1[p] = 0;
	setv[p] = -1;
	if(l == r) {
		int x = iread();
		if(x == 0) lx0[p] = rx0[p] = mx0[p] = 1;
		else lx1[p] = rx1[p] = mx1[p] = sum[p] = 1;
		return;
	}
	int mid = l + r >> 1;
	build(p << 1, l, mid); build(p << 1 | 1, mid + 1, r);
	pushup(p, l, mid, r);
}

inline void change(int p, int l, int r, int x, int y, int c) {
	if(x <= l && r <= y) {
		if(c == 0) {
			lx0[p] = rx0[p] = mx0[p] = r - l + 1;
			lx1[p] = rx1[p] = mx1[p] = sum[p] = 0;
		} else {
			lx0[p] = rx0[p] = mx0[p] = 0;
			lx1[p] = rx1[p] = mx1[p] = sum[p] = r - l + 1;
		}
		xorv[p] = 0; setv[p] = c;
		return;
	}
	int mid = l + r >> 1;
	pushdown(p, l, mid, r);
	if(x <= mid) change(p << 1, l, mid, x, y, c);
	if(y > mid) change(p << 1 | 1, mid + 1, r, x, y, c);
	pushup(p, l, mid, r);
}

inline void rev(int p, int l, int r, int x, int y) {
	if(x <= l && r <= y) {
		swap(lx0[p], lx1[p]); swap(rx0[p], rx1[p]);
		swap(mx0[p], mx1[p]); sum[p] = r - l + 1 - sum[p];
		if(xorv[p]) xorv[p] = 0;
		else if(!~setv[p]) xorv[p] = 1;
		else if(setv[p] == 0) setv[p] = 1;
		else if(setv[p] == 1) setv[p] = 0;
		return;
	}
	int mid = l + r >> 1;
	pushdown(p, l, mid, r);
	if(x <= mid) rev(p << 1, l, mid, x, y);
	if(y > mid) rev(p << 1 | 1, mid + 1, r, x, y);
	pushup(p, l, mid, r);
}

inline int querysum(int p, int l, int r, int x, int y) {
	if(x <= l && r <= y) return sum[p];
	int mid = l + r >> 1, res = 0;
	pushdown(p, l, mid, r);
	if(x <= mid) res += querysum(p << 1, l, mid, x, y);
	if(y > mid) res += querysum(p << 1 | 1, mid + 1, r, x, y);
	return res;
}

struct _ans {
	int lx, rx, mx, sum;
};

inline _ans querymax(int p, int l, int r, int x, int y) {
	if(x == l && r == y) return (_ans){lx1[p], rx1[p], mx1[p], sum[p]};
	int mid = l + r >> 1;
	pushdown(p, l, mid, r);
	if(y <= mid) return querymax(p << 1, l, mid, x, y);
	else if(x > mid) return querymax(p << 1 | 1, mid + 1, r, x, y);
	else {
		_ans L = querymax(p << 1, l, mid, x, mid), R = querymax(p << 1 | 1, mid + 1, r, mid + 1, y);
		_ans ans;
		ans.sum = L.sum + R.sum;
		ans.lx = L.lx;
		if(L.sum == mid - l + 1) ans.lx += R.lx;
		ans.rx = R.rx;
		if(R.sum == r - mid) ans.rx += L.rx;
		ans.mx = max(max(L.mx, R.mx), L.rx + R.lx);
		return ans;
	}
}

int main() {
	n = iread(); m = iread();
	build(1, 1, n);
	while(m--) {
		int opt = iread(), l = iread(), r = iread(); l++; r++;
		if(opt == 0 || opt == 1) change(1, 1, n, l, r, opt);
		else if(opt == 2) rev(1, 1, n, l, r);
		else if(opt == 3) printf("%d\n", querysum(1, 1, n, l, r));
		else if(opt == 4) printf("%d\n", querymax(1, 1, n, l, r).mx);
	}
	return 0;
}

附暴力
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 100005;

int n, m, num[maxn];

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

inline void output() {
	for(int i = 1; i <= n; i++) printf("%d ", num[i]);
	printf("\n");
}

int main() {
	freopen("1.in", "r", stdin);
	freopen("1.ans", "w", stdout);
	n = iread(); m = iread();
	for(int i = 1; i <= n; i++) num[i] = iread();
	while(m--) {
		int opt = iread(), l = iread(), r = iread(); l++; r++;
		if(opt == 0) {
			for(int i = l; i <= r; i++) num[i] = 0;
		}
		else if(opt == 1) {
			for(int i = l; i <= r; i++) num[i] = 1;
		}
		else if(opt == 2) {
			for(int i = l; i <= r; i++) num[i] ^= 1;
		}
		else if(opt == 3) {
			int ans = 0;
			for(int i = l; i <= r; i++) ans += num[i] == 1;
			printf("%d\n", ans);
		}
		else {
			int ans = 0, res = 0;
			for(int i = l; i <= r; i++)
				if(num[i] == 0) ans = max(ans, res), res = 0;
				else res++;
			ans = max(ans, res);
			printf("%d\n", ans);
		}
//		output();
	}
	return 0;
}

和mk
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <algorithm>

using namespace std;

typedef long long LL;

inline int rd(int x) {
	return (LL)rand() * rand() % x + 1;
}

int main() {
	freopen("1.in", "w", stdout);
	srand(time(0));

	int n = 1000, m = 1000;
	printf("%d %d\n", n, m);
	for(int i = 1; i <= n; i++) printf("%d ", rd(2) - 1);
	printf("\n");
	for(int i = 1; i <= m; i++) {
		int opt = rd(5) - 1, l = rd(n), r = rd(n);
//		for(; opt == 3; opt = rd(5) - 1);
		if(l > r) swap(l, r);
		printf("%d %d %d\n", opt, l - 1, r - 1);
	}
	return 0;
}



你可能感兴趣的:(【BZOJ1858】[Scoi2010]序列操作【线段树】)