结构体线段树求调
查看原帖
结构体线段树求调
759274
Stevehim楼主2023/1/19 19:08

rt

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <string>
#define maxn 1000010
using namespace std;
typedef long long ll; //开ll
/*
默写结构体线段树
范围为模板1-2
*/

int mod; //如果有模数的话

int z = 1;

struct node {
	int l;
	int r;
	ll val;
	ll add = 0; //加法标记 //开long long !!!! 十年OI一场空,不开longlong 见祖宗
	ll add2 = 1;//乘法标记,默认为1
} a[maxn];

int num[maxn]; //存放值的数组

void build(int p, int l, int r) {
	a[p].l = l;
	a[p].r = r;
	if (l == r) {
		a[p].val = num[l];
		return;
	}
	int mid = (l + r) / 2;
	build(p * 2, l, mid); //建立左子树
	build(p * 2 + 1, mid + 1, r); //建立右子树
	a[p].val = a[p * 2].val + a[p * 2 + 1].val;
	return;
}

/*
spread函数的标注:
1.区间+1的原因:假设 1 2 3 4 5,我的l为1,r为5,那么我用r - l为4,会忽略掉一个端点
(其实根节点设为0有可能不会出错但是根节点设为零p*2会出错)
*/
void spread(int p) { //下传操作
	if (a[p].add) { //先乘后加,必须要打括号!!
		/*a[p * 2].val += (a[p * 2].r - a[p * 2].l + 1) * a[p].add;
		a[p * 2 + 1].val += (a[p * 2 + 1].r - a[p * 2 + 1].l + 1) * a[p].add; //注意:r为右端点,减的时候写前面
		a[p * 2].add += a[p].add, a[p * 2 + 1].add += a[p].add; //对加法标记进行处理
		a[p].add = 0;*/
		a[p * 2].val = (a[p * 2].r - a[p * 2].l + 1 - a[p * 2].val); //实现异或操作
		a[p * 2 + 1].val = (a[p * 2 + 1].r - a[p * 2 + 1].l + 1 - a[p * 2 + 1].val);
		a[p * 2].add += a[p].add;
		a[p * 2 + 1].add += a[p].add;
		a[p].add = 0;
	}
}

void change1(int p, int l, int r, int z) {
	if (l <= a[p].l && r >= a[p].r) { //覆盖了
		a[p].add ^= z;
		a[p].val = r - l + 1 - a[p].val;
		return;
	}
	spread(p);
	int mid = (a[p].l + a[p].r) / 2; //注意:不是 l 与 r !!!
	if (l <= mid) {
		change1(p * 2, l, r, z);
	}
	if (r > mid) {
		change1(p * 2 + 1, l, r, z);
	}
	a[p].val = a[p * 2].val + a[p * 2 + 1].val; //加上值
}

ll ask(int p, int l, int r) {
	if (l <= a[p].l && r >= a[p].r) {
		return a[p].val;
	}
	spread(p);
	ll ans = 0;
	int mid = (a[p].l + a[p].r) / 2;
	if (l <= mid) {
		ans += ask(p * 2, l, r);
	}
	if (r > mid) {
		ans += ask(p * 2 + 1, l, r);
	}
	return ans;
}

int main() {
	int n, m;
	cin >> n >> m;
	memset(num, 0, sizeof(num));
	build(1, 1, n);
	int op, l, r;
	for (int i = 1; i <= m; i++) {
		cin >> op >> l >> r;
		if (op == 0) {
			change1(1, l, r, 1);
		} else {
			cout << ask(1, l, r) << endl;
		}
	}
	return 0;
}
2023/1/19 19:08
加载中...