社区讨论

0分求调

P2572[SCOI2010] 序列操作参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mhjdp11b
此快照首次捕获于
2025/11/04 00:52
4 个月前
此快照最后确认于
2025/11/04 00:52
4 个月前
查看原帖
CPP
#include<iostream>
#include<algorithm>

using namespace std;
const int N = 100005;

struct node {
	int l, r, lmax, rmax, smax, sum, lazy, l0max, r0max, s0max;
}tr[N << 2];
int a[N];

inline int ls(int x) {
	return x << 1;
}

inline int rs(int x) {
	return (x << 1) + 1;
}

inline void pushup(int x) {
	int lc = ls(x), rc = rs(x);
	tr[x].sum = tr[lc].sum + tr[rc].sum;

	tr[x].lmax = tr[lc].lmax;
	if (tr[lc].lmax == tr[lc].r - tr[lc].l + 1) {
		tr[x].lmax += tr[rc].lmax;
	}

	tr[x].rmax = tr[rc].rmax;
	if (tr[rc].rmax == tr[rc].r - tr[rc].l + 1) {
		tr[x].rmax += tr[lc].rmax;
	}

	tr[x].smax = max(max(tr[lc].smax, tr[rc].smax), tr[lc].rmax + tr[rc].lmax);

	tr[x].l0max = tr[lc].l0max;
	if (tr[lc].l0max == tr[lc].r - tr[lc].l + 1) {
		tr[x].l0max += tr[rc].l0max;
	}

	tr[x].r0max = tr[rc].r0max;
	if (tr[rc].r0max == tr[rc].r - tr[rc].l + 1) {
		tr[x].r0max += tr[lc].r0max;
	}

	tr[x].s0max = max(max(tr[lc].s0max, tr[rc].s0max), tr[lc].r0max + tr[rc].l0max);
}

inline void pushdown(int x) {
	if (tr[x].lazy != -1) {
		int lc = ls(x), rc = rs(x);
		if (tr[x].lazy == 0) {
			tr[lc].sum = tr[rc].sum = 0;
			tr[lc].lmax = tr[lc].rmax = tr[lc].smax = 0;
			tr[rc].lmax = tr[rc].rmax = tr[rc].smax = 0;
			tr[lc].l0max = tr[lc].r0max = tr[lc].s0max = tr[lc].r - tr[lc].l + 1;
			tr[rc].l0max = tr[rc].r0max = tr[rc].s0max = tr[rc].r - tr[rc].l + 1;
			tr[lc].lazy = tr[rc].lazy = 0;
		}
		else if (tr[x].lazy == 1) {
			tr[lc].sum = tr[lc].r - tr[lc].l + 1;
			tr[rc].sum = tr[rc].r - tr[rc].l + 1;
			tr[lc].lmax = tr[lc].rmax = tr[lc].smax = tr[lc].r - tr[lc].l + 1;
			tr[rc].lmax = tr[rc].rmax = tr[rc].smax = tr[rc].r - tr[rc].l + 1;
			tr[lc].l0max = tr[lc].r0max = tr[lc].s0max = 0;
			tr[rc].l0max = tr[rc].r0max = tr[rc].s0max = 0;
			tr[lc].lazy = tr[rc].lazy = 1;
		}
		else if (tr[x].lazy == 2) {
			tr[lc].sum = (tr[lc].r - tr[lc].l + 1) - tr[lc].sum;
			tr[rc].sum = (tr[rc].r - tr[rc].l + 1) - tr[rc].sum;
			swap(tr[lc].lmax, tr[lc].l0max);
			swap(tr[lc].rmax, tr[lc].r0max);
			swap(tr[lc].smax, tr[lc].s0max);
			swap(tr[rc].lmax, tr[rc].l0max);
			swap(tr[rc].rmax, tr[rc].r0max);
			swap(tr[rc].smax, tr[rc].s0max);

			if (tr[lc].lazy == -1) tr[lc].lazy = 2;
			else if (tr[lc].lazy == 2) tr[lc].lazy = -1;
			else tr[lc].lazy = 1 - tr[lc].lazy;
			if (tr[rc].lazy == -1) tr[rc].lazy = 2;
			else if (tr[rc].lazy == 2) tr[rc].lazy = -1;
			else tr[rc].lazy = 1 - tr[rc].lazy;
		}
		tr[x].lazy = -1;
	}
}

inline void build(int x, int fl, int fr) {
	tr[x].l = fl, tr[x].r = fr, tr[x].lazy = -1;
	if (fl == fr) {
		tr[x].lmax = tr[x].rmax = tr[x].smax = tr[x].sum = a[fl];
		tr[x].l0max = tr[x].r0max = tr[x].s0max = 1 - a[fl];
	}
	else {
		int mid = (fl + fr) >> 1;
		build(ls(x), fl, mid);
		build(rs(x), mid + 1, fr);
		pushup(x);
	}
}

inline void updt(int x, int fl, int fr, int val) {
	if (tr[x].l >= fl && tr[x].r <= fr) {
		if (val == 0) {
			tr[x].sum = 0;
			tr[x].lmax = tr[x].rmax = tr[x].smax = 0;
			tr[x].l0max = tr[x].r0max = tr[x].s0max = tr[x].r - tr[x].l + 1;
		}
		else if (val == 1) {
			tr[x].sum = tr[x].r - tr[x].l + 1;
			tr[x].lmax = tr[x].rmax = tr[x].smax = tr[x].r - tr[x].l + 1;
			tr[x].l0max = tr[x].r0max = tr[x].s0max = 0;
		}
		else if (val == 2) {
			tr[x].sum = (tr[x].r - tr[x].l + 1) - tr[x].sum;
			swap(tr[x].lmax, tr[x].l0max);
			swap(tr[x].rmax, tr[x].r0max);
			swap(tr[x].smax, tr[x].s0max);
		}
		tr[x].lazy = val;
		return;
	}
	pushdown(x);
	int mid = (tr[x].l + tr[x].r) >> 1;
	if (fl <= mid) updt(ls(x), fl, fr, val);
	if (fr > mid) updt(rs(x), fl, fr, val);
	pushup(x);
}

inline node qry(int x, int fl, int fr) {
	if (tr[x].l >= fl && tr[x].r <= fr) {
		return tr[x];
	}

	pushdown(x);
	int mid = (tr[x].l + tr[x].r) >> 1;

	// 只在左半边
	if (fr <= mid) {
		return qry(ls(x), fl, fr);
	}
	// 只在右半边  
	if (fl > mid) {
		return qry(rs(x), fl, fr);
	}

	// 跨越中点
	node left = qry(ls(x), fl, mid);
	node right = qry(rs(x), mid + 1, fr);

	node ans;
	ans.sum = left.sum + right.sum;
	ans.smax = max({ left.smax, right.smax, left.rmax + right.lmax });

	// 计算lmax:从查询区间左边界开始的最长连续1
	ans.lmax = left.lmax;
	if (left.sum == mid - fl + 1) { // 左半部分[fl,mid]全是1
		ans.lmax += right.lmax;
	}

	// 计算rmax:到查询区间右边界结束的最长连续1
	ans.rmax = right.rmax;
	if (right.sum == fr - mid) { // 右半部分[mid+1,fr]全是1
		ans.rmax += left.rmax;
	}

	return ans;
}

int main(void) {
	int n = 0, m = 0;
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	build(1, 0, n - 1);
	for (int i = 1; i <= m; i++) {
		int l, r, t;
		cin >> t >> l >> r;
		if (t == 0) {
			updt(1, l, r, 0);
		}
		else if (t == 1) {
			updt(1, l, r, 1);
		}
		else if (t == 2) {
			updt(1, l, r, 2);
		}
		else {
			auto k = qry(1, l, r);
			if (t == 3) {
				cout << k.sum << endl;
			}
			else if (t == 4) {
				cout << k.smax << endl;
			}
		}
	}
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...