萌新刚学线段树一天求调模板 玄关
  • 板块灌水区
  • 楼主a_little_carrot
  • 当前回复1
  • 已保存回复1
  • 发布时间2024/11/9 18:38
  • 上次更新2024/11/9 20:49:31
查看原帖
萌新刚学线段树一天求调模板 玄关
1042960
a_little_carrot楼主2024/11/9 18:38
#include "bits/stdc++.h"
using namespace std ;
using ll = long long ;
const int N = 1e5 + 5 ;
int n, m, mod, a[N] ;
class Tree
{
public :
	inline ll ls(ll p) {return p << 1 ;} // 查找左子节点
	inline ll rs(ll p) {return p << 1 | 1 ;} // 查找右子节点
	void BuildTree() {build(1, 1, n) ;} // 建树
	ll Query(ll qx, ll qy, ll l, ll r, ll p) {return query(qx, qy, l, r, p) ;} ; // 查找
	void UpDate(ll pl, ll pr, ll l, ll r, ll p, ll k, ll k2) {return upDate(pl, pr, l, r, p, k, k2) ;} ; // 更新
private :
	ll tree[N << 2], value[N << 2], tag[N << 2], add[N << 2], multiply[N << 2] ;
	void pushUp(ll p)
	{
		value[p] = value[ls(p)] + value[rs(p)] ;
	} ;
	// 向上更新
	inline void f(ll p, ll l, ll r, ll k, ll k2)
	{
		add[p] = add[p] + k * k2 ;
		multiply[p] = multiply[p] * k2 ;
		value[p] = value[p] * multiply[p] + add[p] * (r - l + 1) ;
	}
	// 懒标记
	inline void pushDown(ll p, ll l, ll r)
	{
		ll mid = (l + r) >> 1 ;
		f(ls(p), l, mid, add[p], multiply[p]) ;
		f(rs(p), mid + 1, r, add[p], multiply[p]) ;
		add[p] = 0, multiply[p] = 1 ;
	}
	// 向下传递懒标记
	void build(ll p, ll l, ll r)
	{
		add[p] = 0, multiply[p] = 1 ;
		if(l == r) {value[p] = a[l] ; return ;} ;
		// 叶子结点 赋值
		ll mid = (l + r) >> 1 ;
		build(ls(p), l, mid) ;
		build(rs(p), mid + 1, r) ;
		pushUp(p) ;
		// 更新值
	}
	// 单点建树 建树完毕可得初始各区间值之和
	inline void upDate(ll pl, ll pr, ll l, ll r, ll p, ll k, ll k2)
	//          (更新)左区间/右区间 左区间/右区间 父节点 更新值
	{
		if(pl <= l && r <= pr) // 若更新区间包含当前区间
		{
			f(p, l, r, k, k2) ;
			return ;
		}
		pushDown(p, l, r) ;
		// 下传
		ll mid = (l + r) >> 1 ;
		if(pl <= mid) upDate(pl, pr, l, mid, ls(p), k, k2) ;
		// 更新左部分区间
		if(pr > mid) upDate(pl, pr, mid + 1, r, rs(p), k, k2) ;
		// 更新右部分区间
		pushUp(p) ;
		// 更新本节点
	}
	// 单点更新
	inline ll query(ll qx, ll qy, ll l, ll r, ll p)
	{
		ll res = 0 ;
		if(qx <= l && r <= qy) return value[p] ;
		// 查询区间包含当前区间
		ll mid = (l + r) >> 1 ;
		pushDown(p, l, r) ;
		if(qx <= mid) res += query(qx, qy, l, mid, ls(p)) ;
		if(qy > mid) res += query(qx, qy, mid + 1, r, rs(p)) ;
		return res ;
	}
	// 区间求值
} tree ;
int main()
{
	ios::sync_with_stdio(false) ;
	cin.tie(0) ; cout.tie(0) ;
	int op, x, y, k, k2 ;
	cin >> n >> m >> mod ;
	for(int i = 1 ; i <= n ; ++i) cin >> a[i] ;
	tree.BuildTree() ;
	for(int t = 1 ; t <= m ; ++t)
	{
		cin >> op ;
		if(op == 1)
		{
			cin >> x >> y >> k2 ;
			tree.UpDate(x, y, 1, n, 1, 0, k2) ;
		}
		else if(op == 2)
		{
			cin >> x >> y >> k ;
			tree.UpDate(x, y, 1, n, 1, k, 0) ;
		}
		else
		{
			cin >> x >> y ;
			cout << tree.Query(x, y, 1, n, 1) << endl ;
		}
	}
	return 0 ;
}
2024/11/9 18:38
加载中...