1277. 維護序列 (線段樹來懶惰標記模板)

題目鏈接:https://www.acwing.com/problem/content/1279/

解題思路:直接開一個線段樹,然後開懶惰標記,在pushdown的時候,先算乘法,再算除法。當乘法來的時候,將當前節點的add同時也乘上剛來的數字;其實,這類題都是這樣,要去看一下法則的優先級。

貼上蒟蒻的代碼一份

#include <iostream>
#include <cstdio>

using namespace std;

typedef long long LL;

const int maxn = 1e5 + 5;

int n, m, mod;
int a[maxn];

struct Treement {
	int l, r;
	LL sum;
	LL add, mul;
}tr[maxn * 4];

inline void pushup(int u) {
	tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
	tr[u].sum %= mod;
}

inline void pushdown(int u) {
	Treement &nodel = tr[u << 1], &noder = tr[u << 1 | 1];
	nodel.add *= tr[u].mul; nodel.mul *= tr[u].mul; nodel.sum *= tr[u].mul;
	noder.add *= tr[u].mul; noder.mul *= tr[u].mul; noder.sum *= tr[u].mul;
	nodel.add += tr[u].add, nodel.sum += tr[u].add * (nodel.r - nodel.l + 1);
	noder.add += tr[u].add, noder.sum += tr[u].add * (noder.r - noder.l + 1);
	
	nodel.add %= mod; nodel.mul %= mod; nodel.sum %= mod;
	noder.add %= mod; noder.mul %= mod; noder.sum %= mod;
	
	tr[u].mul = 1, tr[u].add = 0;
}

inline void build(int u, int l, int r) {
	tr[u] = {l, r, 0, 0, 1};
	if(l == r) {
		tr[u].sum = a[l];
		return;
	}
	
	int mid = l + r >> 1;
	build(u << 1, l, mid);
	build(u << 1 | 1, mid + 1, r);
	pushup(u);	
}

inline void modify_mul(int u, int l, int r, LL x) {
	if(l <= tr[u].l && tr[u].r <= r) {
		tr[u].add *=  x; tr[u].add %= mod;
		tr[u].mul *= x; tr[u].mul %= mod;
		tr[u].sum *= x; tr[u].sum %= mod;
		return;
	}
	
	pushdown(u);
	int mid = tr[u].l + tr[u].r >> 1;
	if(l <= mid) modify_mul(u << 1, l, r, x);
	if(r > mid) modify_mul(u << 1 | 1, l, r, x);
	pushup(u);
}

inline void modify_add(int u, int l, int r, LL x) {
	if(l <= tr[u].l && tr[u].r <= r) {
		tr[u].add += x; tr[u].add %= mod;
		tr[u].sum += x * (tr[u].r - tr[u].l + 1);
		tr[u].sum %= mod;
		return;
	}
	
	pushdown(u);
	int mid = tr[u].l + tr[u].r >> 1;
	if(l <= mid) modify_add(u << 1, l, r, x);
	if(r > mid) modify_add(u << 1 | 1, l, r, x);
	pushup(u);
}

inline LL query(int u, int l, int r) {
	if(l <= tr[u].l && tr[u].r <= r) return tr[u].sum % mod;
	
	pushdown(u);
	int mid = tr[u].l + tr[u].r >> 1;
	LL res = 0;
	if(l <= mid) res = query(u << 1, l, r);
	if(r > mid) res += query(u << 1 | 1, l, r);
	pushup(u);
	
	return res % mod;	
}

int main(void) {
//	freopen("in.txt", "r", stdin);
	scanf("%d%d", &n, &mod);
	for(int i = 1; i <= n; i ++) {
		scanf("%d", &a[i]);
		a[i] %= mod;
	}
	
	build(1, 1, n);
	
	scanf("%d", &m);
	while(m --) {
		int op, t, g;
		LL c;
		scanf("%d%d%d", &op, &t, &g);
		if(op == 1) {
			scanf("%lld", &c);
			c %= mod;
			modify_mul(1, t, g, c);
		} else if(op == 2) {
			scanf("%lld", &c);
			c %= mod;
			modify_add(1, t, g, c);
		} else {
			printf("%lld\n", query(1, t, g));
		}
		
	}
	
	
	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章