4号关注,线段树求助,内有极小的hack
查看原帖
4号关注,线段树求助,内有极小的hack
347589
Zelotz楼主2022/2/10 19:53
#include <bits/stdc++.h>
using namespace std;
#define srand srand(time(NULL))
#define random(x) rand() % (x)
#define il inline
#define ptc putchar
#define reg register
#define mp make_pair
typedef __int128 LL;
typedef long long ll;
typedef pair<int, int> PII;
namespace cyyh {
	template <typename T>
	il void read(T &x) {
		x = 0; T f = 1; char ch;
		while (!isdigit(ch = getchar())) f -= (ch == '-') << 1;
		while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch & 15), ch = getchar(); x *= f;
	}
	template <typename T>
	il void write(T x) {
		if (x < 0) ptc('-'), x = -x;
		if (x > 9) write(x / 10);
		ptc(x % 10 + '0');
	}
	template <typename T>
	il T lowbit(const T &x) {
		return x & -x;
	}
}
using namespace cyyh; 
const int N = 4e5 + 5;
int n, m, a[N];
struct node {
	int sum0, sum1, mx0, mx1, zq0, zq1, yq0, yq1, tag;
	// tag1表示区间更改的数,初始值为-1
	// tag2表示区间是否取反
	// sum表示区间内该数字的个数
	// mx表示区间内该数字的最大的连续一段
	// zq表示区间左端点开始该数最长的连续个数
	// yq表示区间右端点开始该数最长的连续个数
} tr[N];
void pushup(int id, int l, int r) {
	int ls = id << 1, rs = id << 1 | 1;
	tr[id].sum0 = tr[ls].sum0 + tr[rs].sum0;
	tr[id].sum1 = tr[ls].sum1 + tr[rs].sum1;
	tr[id].mx0 = max(tr[ls].yq0 + tr[rs].zq0, max(tr[ls].mx0, tr[rs].mx0));
	tr[id].mx1 = max(tr[ls].yq1 + tr[rs].zq1, max(tr[ls].mx1, tr[rs].mx1));
	tr[id].zq0 = tr[ls].zq0, tr[id].yq0 = tr[rs].yq0;
	tr[id].zq1 = tr[ls].zq1, tr[id].yq1 = tr[rs].yq1;
	int mid = l + r >> 1;
	if (tr[ls].zq0 == mid - l + 1) tr[id].zq0 += tr[rs].zq0;
	if (tr[ls].zq1 == mid - l + 1) tr[id].zq1 += tr[rs].zq1;
	if (tr[ls].yq0 == r - mid) tr[id].yq0 += tr[rs].yq0;
	if (tr[ls].yq1 == r - mid) tr[id].yq1 += tr[rs].yq1;
}
void pushdown(int id, int l, int r) {
	int mid = l + r >> 1, ls = id << 1, rs = id << 1 | 1;
	if (tr[id].tag == -1) return ;
	if (!tr[id].tag) {
		tr[ls].tag = tr[ls].mx1 = tr[ls].sum1 = tr[ls].yq1 = tr[ls].zq1 = 0;
		tr[ls].mx0 = tr[ls].sum0 = tr[ls].yq0 = tr[ls].zq0 = mid - l + 1;
		tr[rs].tag = tr[rs].mx1 = tr[rs].sum1 = tr[rs].yq1 = tr[rs].zq1 = 0;
		tr[rs].mx0 = tr[rs].sum0 = tr[rs].yq0 = tr[rs].zq0 = r - mid;
	} else if (tr[id].tag == 1) {
		tr[ls].tag = 1;
		tr[ls].mx0 = tr[ls].sum0 = tr[ls].yq0 = tr[ls].zq0 = 0;
		tr[ls].mx1 = tr[ls].sum1 = tr[ls].yq1 = tr[ls].zq1 = mid - l + 1;
		tr[rs].tag = 1;
		tr[rs].mx0 = tr[rs].sum0 = tr[rs].yq0 = tr[rs].zq0 = 0;
		tr[rs].mx1 = tr[rs].sum1 = tr[rs].yq1 = tr[rs].zq1 = r - mid;
	} else {
		swap(tr[ls].mx0, tr[ls].mx1);
		swap(tr[ls].sum0, tr[ls].sum1);
		swap(tr[ls].yq0, tr[ls].yq1);
		swap(tr[ls].zq0, tr[ls].zq1);
		if (tr[ls].tag == 1 || tr[ls].tag == 0) tr[ls].tag = !tr[ls].tag;
		else if (tr[ls].tag == -1) tr[ls].tag = 2;
		else tr[ls].tag = -1;
		swap(tr[rs].mx0, tr[rs].mx1);
		swap(tr[rs].sum0, tr[rs].sum1);
		swap(tr[rs].yq0, tr[rs].yq1);
		swap(tr[rs].zq0, tr[rs].zq1);
		if (tr[rs].tag == 1 || tr[rs].tag == 0) tr[rs].tag = !tr[rs].tag;
		else if (tr[rs].tag == -1) tr[rs].tag = 2;
		else tr[rs].tag = -1;
	}
	tr[id].tag = -1;
}
void modify(int l, int r, int x, int y, int id, int op) {
	// op为指定操作 
	if (l > y || r < x) return ;
	if (l >= x && r <= y) {
		if (!op) {
			tr[id].mx1 = tr[id].sum1 = tr[id].tag = tr[id].yq1 = tr[id].zq1 = 0;
			tr[id].sum0 = tr[id].mx0 = tr[id].yq0 = tr[id].zq0 = r - l + 1;
		} else if (op == 1) {
			tr[id].tag = 1;
			tr[id].mx1 = tr[id].sum1 = tr[id].tag = tr[id].yq1 = r - l + 1;
			tr[id].sum0 = tr[id].mx0 = tr[id].yq0 = tr[id].zq0 = 0;
		} else {
			swap(tr[id].mx0, tr[id].mx1);
			swap(tr[id].sum0, tr[id].sum1);
			swap(tr[id].yq0, tr[id].yq1);
			swap(tr[id].zq0, tr[id].yq1);
//			if(~tr[id].tag && tr[id].tag != 2) tr[id].tag ^= 1;
//			else tr[id].tag = (tr[id].tag == 2 ? -1 : 2);
			if (tr[id].tag == 1 || tr[id].tag == 0) tr[id].tag = !tr[id].tag;
			else if (tr[id].tag == -1) tr[id].tag = 2;
			else tr[id].tag = -1;
		} 
		return ;
	}
	pushdown(id, l, r);
	int mid = l + r >> 1;
	modify(l, mid, x, y, id << 1, op), modify(mid + 1, r, x, y, id << 1 | 1, op);
	pushup(id, l, r);
}
int query(int l, int r, int x, int y, int id) {
	if (l > y || r < x) return 0;
	if (l >= x && r <= y) return tr[id].sum1;
	int mid = l + r >> 1;
	pushdown(id << 1, l, r);
	return query(l, mid, x, y, id << 1) + query(mid + 1, r, x, y, id << 1 | 1);
}
node query2(int l, int r, int x, int y, int id) {
	if (l >= x && r <= y) return tr[id];
	int mid = l + r >> 1, ls = id << 1, rs = id << 1 | 1;
	pushdown(id, l, r);
	if (y <= mid) return query2(l, mid, x, y, ls);
	else if (x > mid) return query2(mid + 1, r, x, y, rs);
	node a = query2(l, mid, x, y, ls), b = query2(mid + 1, r, x, y, rs), res;
	// pushup
	res.mx1 = max(a.yq1 + b.zq1, max(a.mx1, b.mx1));
	res.zq1 = a.zq1, res.yq1 = b.yq1;
	if (a.zq1 == mid - l + 1) res.zq1 += b.zq1;
	if (b.yq1 == r - mid) res.yq1 += a.yq1;
	return res;
}
void build(int l, int r, int id) {
	tr[id].tag = -1;
	if (l == r) {
		tr[id].mx0 = tr[id].sum0 = tr[id].yq0 = tr[id].zq0 = !a[l];
		tr[id].mx1 = tr[id].sum1 = tr[id].yq1 = tr[id].zq1 = a[l];
		return ;
	}
	int mid = l + r >> 1;
	build(l, mid, id << 1), build(mid + 1, r, id << 1 | 1);
	pushup(id, l, r);
}
int main() {
	read(n), read(m);
	for (int i = 1; i <= n; ++i) read(a[i]);
	build(1, n, 1);
	//modify(1, n, 2, 3, 1, 2);
//	for (int i = 1; i <= n; ++i) {
//		for (int j = i; j <= n; ++j) {
//			cout << i << ' ' << j << ' ' << query(1, n, i, j, 1) << ' ' << endl;
//		}
//	}
	//write(query(1, n, 1, 3, 1)), ptc('\n');
//	return 0;
	while (m--) {
		int op, l, r;
		read(op), read(l), read(r);
		++l, ++r;
		if (op == 0) modify(l, r, 1, n, 1, 0);
		else if (op == 1) modify(1, n, l, r, 1, 1);
		else if (op == 2) modify(1, n, l, r, 1, 2);
		else if (op == 3) write(query(1, n, l, r, 1)), ptc('\n');
		else if (op == 4) write(query2(1, n, l, r, 1).mx1), ptc('\n');
	}
	return 0;
}

萌新第4次写线段树,hack如下:

3 2
1 0 0
2 1 2
4 0 2

答案显然是3,而modify确实修改成功了的,查询的时候却总是出错,但是查询我死活看不出来问题在哪

2022/2/10 19:53
加载中...