718 字
4 分钟
P3373 【模板】线段树 2
题目
题解
线段树
考虑两个tag,mul与add
表示[l, mid]
[mid + 1, r]
这两个区间分别需要* mul + tag
下传标记的时候[l, mid]
[mid + 1, r]
这两个子区间的tag,mul tag直接*mul[u]
,add tag要* mul[u] + tag[u]
锅
1.change最后返回前要pushup一下
2.下传的时候u要穿ls,rs(
3.不开longlong见祖宗
代码
#include<bits/stdc++.h>const int N = 1e5 + 10;int n;using namespace std;#define int long longint a[N];const int mod = 571373;
namespace Segmenttree{ #define ls (u << 1) #define rs ((u << 1) | 1) int tree[N << 2]; int tagcheng[N << 2], tagjia[N << 2]; void init() { for(int i = 1;i < 4 * n;i++) tagcheng[i] = 1, tagjia[i] = 0; } void pushup(int u) { tree[u] = (tree[ls] + tree[rs]) % mod; }
void build(int u, int l, int r) { if(l == r) { tree[u] = a[l]; return; } int mid = (l + r) >> 1; build(ls, l, mid); build(rs, mid + 1, r); pushup(u); }
void pushdown(int u, int l, int r) { int mid = (l + r) >> 1; //[l, mid]、[mid + 1, r] tree[ls] = (tree[ls] * tagcheng[u] + tagjia[u] * (mid - l + 1)) % mod; tree[rs] = (tree[rs] * tagcheng[u] + tagjia[u] * (r - mid)) % mod; tagcheng[ls] = tagcheng[ls] * tagcheng[u] % mod; tagcheng[rs] = tagcheng[rs] * tagcheng[u] % mod; tagjia[ls] = (tagjia[ls] * tagcheng[u] + tagjia[u]) % mod; tagjia[rs] = (tagjia[rs] * tagcheng[u] + tagjia[u]) % mod; tagjia[u] = 0; tagcheng[u] = 1; }
void change(int u, int l, int r, int L, int R, int val, int type) { if(L <= l && r <= R) {// cout << l << " " << r << " was included"<<endl; if(type == 0) { tree[u] = (tree[u] + val * (r - l + 1)) % mod; tagjia[u] = (tagjia[u] + val) % mod; } else {
tree[u] = tree[u] * val % mod; tagcheng[u] = tagcheng[u] * val % mod; tagjia[u] = tagjia[u] * val % mod;// if(l == 4 && r == 4) cout << u<<" "<< val << " " << type << "qaqaqaq"<< " " << tree[u] << " "<< endl; } return; }// cout << l << " " << r << endl; pushdown(u, l, r); int mid = (l + r) >> 1; if(L <= mid) change(ls, l, mid, L, R, val, type); if(R > mid) change(rs, mid + 1, r, L, R, val, type); pushup(u); }
int query(int u, int l, int r, int L, int R) { if(L <= l && r <= R) {// cout << "query : " << l << " " << r << "sum: " << tree[u] << " " << u << endl; return tree[u]; } int ans = 0; pushdown(u, l, r); int mid = (l + r) >> 1; if(L > r || R < l) return 0; if(L <= mid) ans = (ans + query(ls, l, mid, L, R)) % mod; if(R > mid) ans = (ans + query(rs, mid + 1, r, L, R)) % mod;// cout << "query : " << l << " " << r << "sum: " << ans << " " << u << endl; return ans; }}signed main(){// ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int q, m; cin >> n >> q >> m; for(int i = 1;i <= n;i++) cin >> a[i]; int opt; Segmenttree::init(); Segmenttree::build(1, 1, n); while(q--) { int x, y, k; cin >> opt; if(opt == 1) { cin >> x >> y >> k; Segmenttree::change(1, 1, n, x, y, k, 1);// cout << "qwq" << Segmenttree::query(1, 1, n, 4, 4) << '\n'; } else if(opt == 2) { cin >> x >> y >> k; Segmenttree::change(1, 1, n, x, y, k, 0);// cout << "qwq" << " " << Segmenttree::query(1, 1, n, x, y) << '\n'; } else { cin >> x >> y; cout << Segmenttree::query(1, 1, n, x, y) << '\n'; } } return 0;}
P3373 【模板】线段树 2
https://blog.histcat.top/posts/p3373/