P3870 [TJOI2009] 開關

Coder2023發表於2024-04-03

題目大意
進行兩項區間操作,一種是修改區間和,一種是查詢區間和,資料範圍不大,顯然,可以以線段樹解,其中,修改區間和比較簡單,用區間總長度減去區間和即可,即\(tree[root].value =(tree[root].r - tree[root].l + 1) - tree[root].value\),區間查詢就是普通的線段樹區間查詢。複雜度分析,修改查詢皆為\(O(logn)\)
程式碼如下

#include <iostream>
#include <cstdio>
using namespace std;
int n, m;
const int maxn = 1e5 + 5;
struct segment_tree
{
	int l, r;
	int value;
	int lazy_tag;
};
segment_tree tree[maxn * 4];
void pushup(int root)
{
	tree[root].value = tree[root << 1].value + tree[(root << 1) + 1].value;
}
void build(int root, int l, int r)
{
	tree[root].l = l, tree[root].r = r;
	if(l == r)
	{
		tree[root].value = 0;
		return;
	}
	int mid = (l + r) >> 1;
	build(root << 1, l, mid);
	build((root << 1) + 1, mid + 1, r);
	pushup(root);
}
void pushdown(int root)
{
	if(tree[root].lazy_tag == 0) return;
	tree[root << 1].lazy_tag ^= 1, tree[(root << 1) + 1].lazy_tag ^= 1;
	tree[root << 1].value = (tree[root << 1].r - tree[root << 1].l + 1) - tree[root << 1].value;
	tree[(root << 1) + 1].value = tree[(root << 1) + 1].r - tree[(root << 1) + 1].l + 1 -tree[(root << 1) + 1].value;
	tree[root].lazy_tag = 0;
}
void update(int root, int L, int R)
{
	int l = tree[root].l, r = tree[root].r;
	if(L <= l && r <= R)
	{
		tree[root].lazy_tag ^= 1;
		tree[root].value = (r - l + 1) - tree[root].value;
		return;
	}
	int mid = (l + r) >> 1;
	tree[root].lazy_tag %= 2;
	pushdown(root);
	if(L <= mid) update(root << 1, L, R);
	if(R > mid)update((root << 1) + 1, L, R);
	pushup(root);
}
int query(int root, int L, int R)
{
	int l = tree[root].l, r = tree[root].r;
	if(L <= l && r <= R) return tree[root].value;
	int res = 0;
	int mid = (l + r) >> 1;
	tree[root].lazy_tag %= 2;
	pushdown(root);
	if(L <= mid) res += query(root << 1, L, R);
	if(R > mid) res += query((root << 1) + 1, L, R);
	return res;
}
int main()
{
	scanf("%d%d", &n, &m);
	build(1, 1, n);
	while(m--)
	{
		int opt;
		scanf("%d", &opt);
		if(opt == 0)
		{
			int a, b;
			scanf("%d%d", &a, &b);
			update(1, a, b);
		}
		else
		{
			int a, b;
			scanf("%d%d", &a, &b);
			printf("%d\n", query(1, a, b));
		}
	}
	return 0;
}

相關文章