P2023 [AHOI2009]维护序列 - 线段树

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Fantasy_World/article/details/82956152

记得及时更新sum(每次修改都更新),写成一个update函数比较好,因为很多时候会忘了%
还有懒标记是标记在这个点本身上的
然后就是左儿子和右儿子一定要看清楚。。。
一个是n * 2 ,一个是 n * 2 + 1 ,涉及到这部分的代码一定要专注
乘法标记优先级大于加法,并且对加法标记也有作用
若要增加加法标记,先让乘法标记作用一下加法标记,再增加加法标记
然后注意乘法标记要初始化为乘法单位元,就是1
每次清空也要初始化为1,建树的时候注意初始化乘法标记

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 100000 + 10;
typedef long long ll;
int n,m,p,a[MAXN];
struct segment{
	ll mul, add, sum, siz;
}tr[MAXN*4];

void update(int now) {
	tr[now].sum = tr[now*2].sum + tr[now*2+1].sum;
	tr[now].sum %= p;
}

void build(int now, int l, int r) {
	tr[now].mul = 1;
	if(l == r) {
		tr[now].siz = 1;
		tr[now].sum = a[l];
		return;
	}
	int mid = l + r >> 1;
	build(now*2, l, mid);
	build(now*2+1, mid+1, r);
	tr[now].sum = tr[now*2].sum + tr[now*2+1].sum;
	tr[now].sum %= p;
	tr[now].siz = tr[now*2].siz + tr[now*2+1].siz;
}

void down(int now) {
	int mul = tr[now].mul;
	int add = tr[now].add;
	
	tr[now*2].sum *= mul;
	tr[now*2].sum %= p;
	tr[now*2].sum += add * tr[now*2].siz;
	tr[now*2].sum %= p;
	
	tr[now*2+1].sum *= mul;
	tr[now*2+1].sum %= p;
	tr[now*2+1].sum += add * tr[now*2+1].siz;
	tr[now*2+1].sum %= p;
	
	tr[now*2].mul *= mul;
	tr[now*2].add *= mul;
	tr[now*2].add += add;
	
	tr[now*2].mul %= p;
	tr[now*2].add %= p;
	
	tr[now*2+1].mul *= mul;
	tr[now*2+1].add *= mul;
	
	tr[now*2+1].add += add;
	tr[now*2+1].mul %= p;
	tr[now*2+1].add %= p;
	
	tr[now].mul = 1;
	tr[now].add = 0; 
}

void mul_modi(int now, int l, int r, int x, int y, int k) {
	if(x <= l && r <= y) {
		tr[now].sum *= k;
		tr[now].sum %= p;
		
		tr[now].mul *= k;
		tr[now].mul %= p;
		
		tr[now].add *= k;
		tr[now].add %= p;
		return;
	}
	down(now);
	int mid = l + r >> 1;
	if(x <= mid)
		mul_modi(now*2, l, mid, x, y, k);
	if(y > mid)
		mul_modi(now*2+1, mid+1, r, x, y, k);
	update(now);
}

void add_modi(int now, int l, int r, int x, int y, int k){
	if(x <= l && r <= y) {
		tr[now].sum += k * tr[now].siz;
		tr[now].sum %= p;
		
		tr[now].add += k;
		tr[now].add %= p;
		return;
	}
	down(now);
	int mid = l + r >> 1;
	if(x <= mid)
		add_modi(now*2, l, mid, x, y, k);
	if(y > mid)
		add_modi(now*2+1, mid+1, r, x, y, k);
	update(now);
}

ll query(int now, int l, int r, int x, int y) {
	if(x <= l && r <= y) {
		return tr[now].sum;
	}
	down(now);
	int mid = l + r >> 1;
	ll sum = 0;
	if(x <= mid) {
		sum += query(now*2, l, mid, x, y);
		sum %= p;
	}
	if(y > mid) {
		sum += query(now*2+1, mid+1, r, x, y);
		sum %= p;
	}
	return sum;
}
int main() {
	scanf("%d%d", &n, &p);
	for(int i=1; i<=n; i++) {
		scanf("%d", &a[i]);
	}
	build(1, 1, n);
	scanf("%d", &m);
	for(int i=1; i<=m; i++) {
		int cmd, x, y, c;
		scanf("%d", &cmd);
		if(cmd == 1) {//mul
			scanf("%d%d%d", &x, &y, &c);
			mul_modi(1, 1, n, x, y, c);
		} else if(cmd == 2) {
			scanf("%d%d%d", &x, &y, &c);
			add_modi(1, 1, n, x, y, c);
		} else {
			scanf("%d%d", &x, &y);
			printf("%lld\n", query(1, 1, n, x, y));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Fantasy_World/article/details/82956152
今日推荐