当前位置: 代码迷 >> 综合 >> 洛谷P2023 bzoj1798 [AHOI2009]维护序列
  详细解决方案

洛谷P2023 bzoj1798 [AHOI2009]维护序列

热度:48   发布时间:2023-11-21 12:01:42.0

线段树裸题不解释,注意取膜和乘法标记对加法标记的影响就好了

#include <bits/stdc++.h>
#define Ls(x) x << 1
#define Rs(x) x << 1 | 1
using namespace std;
int n, m;
long long mod;
const int maxn = 100000 + 10;
long long a[maxn];
template<class T>void read(T &x)
{x = 0;int f = 0;int ch = getchar();while(ch < '0' || ch > '9')  {f |= (ch == '-'); ch = getchar();}while(ch >=  '0'&&ch <= '9'){x = x * 10+(ch^48); ch = getchar();}x = f?-x:x;return;
}
struct SegmentTree{int l, r, len;long long tag;long long mult;long long val;SegmentTree(){tag = 0;val = 0;mult = 1;l = r = len = 0;}
}tre[maxn << 2];
void build(int rt, int l, int r)
{tre[rt].l = l, tre[rt].r = r, tre[rt].len = r - l + 1;if(l == r) {tre[rt].val = a[l];return ;}int mid = (l + r) >> 1;build(Ls(rt), l, mid);build(Rs(rt), mid + 1, r);tre[rt].val = (tre[Ls(rt)].val + tre[Rs(rt)].val) % mod;
}
void push_down(int rt) {tre[Ls(rt)].mult =  tre[Ls(rt)].mult * tre[rt].mult % mod;tre[Ls(rt)].tag = (tre[Ls(rt)].tag * tre[rt].mult + tre[rt].tag) % mod;tre[Ls(rt)].val  = (tre[Ls(rt)].val  * tre[rt].mult + tre[rt].tag * (tre[Ls(rt)].len)) % mod;tre[Rs(rt)].mult =  tre[Rs(rt)].mult * tre[rt].mult % mod;tre[Rs(rt)].tag = (tre[Rs(rt)].tag * tre[rt].mult + tre[rt].tag) % mod;tre[Rs(rt)].val  = (tre[Rs(rt)].val  * tre[rt].mult + tre[rt].tag * (tre[Rs(rt)].len)) % mod;tre[rt].mult=1;tre[rt].tag=0;
}
void update(int rt, int L, int R, long long delta, int k) {int l = tre[rt].l, r = tre[rt].r;int mid = (l + r) >> 1;if(l >= L && r <= R) {if(k == 2) {tre[rt].tag = (tre[rt].tag + delta) % mod;tre[rt].val = (tre[rt].val + delta * tre[rt].len) % mod;}else {tre[rt].mult = tre[rt].mult * delta % mod;tre[rt].tag = tre[rt].tag * delta % mod;tre[rt].val = tre[rt].val * delta % mod;}return ;}if(tre[rt].mult != 1 || tre[rt].tag ) push_down(rt);if(L <= mid) update(Ls(rt), L, R, delta, k);if(R > mid)  update(Rs(rt), L, R, delta, k);tre[rt].val = (tre[Ls(rt)].val + tre[Rs(rt)].val) % mod;return ;
}
long long query(int rt, int L, int R) {int l = tre[rt].l, r = tre[rt].r;int mid = (l + r) >> 1;if(l >= L && r <= R) {return tre[rt].val;}if(tre[rt].mult != 1 || tre[rt].tag ) push_down(rt);long long res = 0;if(L <= mid) res += query(Ls(rt), L, R);if(mid < R) res += query(Rs(rt), L, R);return res % mod;}signed main()
{read(n); read(mod);for(int i = 1; i <= n; i++) read(a[i]);read(m);build(1, 1, n);for(int i = 1, opt, l, r; i <= m; i++) {read(opt); read(l); read(r);long long dif;if(opt == 3) {printf("%lld\n", query(1, l, r));}else {read(dif);update(1, l ,r, dif, opt);}}return 0;
}