模板 - 区间乘&区间加

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
 
using namespace std;
 
typedef pair<int, int> PII;
typedef pair<int, PII> PIII;
typedef long long ll;

const int N = 100010;

int n, mod;
int a[N];
struct Node
{
	int l, r;
	ll sum;
	ll mul, add;
}tr[N * 4];

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

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

void pushdown(int u)
{
	auto &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
	
	left.sum = (left.sum * root.mul + root.add * (left.r - left.l + 1)) % mod;
	left.mul = left.mul * root.mul % mod;
	left.add = left.add * root.mul % mod;
	left.add = (left.add + root.add) % mod;
	
	right.sum = (right.sum * root.mul + root.add * (right.r - right.l + 1)) % mod;
	right.mul = right.mul * root.mul % mod;
	right.add = right.add * root.mul % mod;
	right.add = (right.add + root.add) % mod;
	
	root.mul = 1, root.add = 0;
}

void modify(int u, int l, int r, ll c, int op)
{
	if(l <= tr[u].l && tr[u].r <= r)
	{
		if(op == 1)//乘 
		{
			tr[u].sum = (tr[u].sum * c) % mod;
			tr[u].mul = (tr[u].mul * c) % mod;
			tr[u].add = (tr[u].add * c) % mod;
		}
		else
		{
			tr[u].sum = (tr[u].sum + c * (tr[u].r - tr[u].l + 1)) % mod;
			tr[u].add = (tr[u].add + c) % mod;
		}
		return;
	}
	
	pushdown(u);
	int mid = tr[u].l + tr[u].r >> 1;
	if(l <= mid)modify(u << 1, l, r, c, op);
	if(mid + 1 <= r)modify(u << 1 | 1, l, r, c, op);
	pushup(u);
}

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

int main()
{
	IOS
	cin >> n >> mod;
	for(int i = 1; i <= n; i ++)cin >> a[i];
	
	build(1, 1, n);
	
	int m;
	cin >> m;
	while(m --)
	{
		int op, l, r;
		ll c;
		cin >> op >> l >> r;
		if(op == 1)//[l, r]范围内*c
		{
			cin >> c;
			modify(1, l, r, c, 1);
		}
		else if(op == 2)//[l, r]范围内+c
		{
			cin >> c;
			modify(1, l, r, c, 2);
		}
		else//[l, r]范围内的和%mod
		{
			cout << query(1, l, r) << endl;
		}
	}
	
	return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值