1 #include<iostream> 2 #include<string> 3 #define ll long long 4 const int N = 1e5 + 5; 5 6 using namespace std; 7 8 ll tree[N<<2]; // 线段树,可以是对应的结构体 9 ll lz[N<<2]; // 延迟标记,也可以是结构体 10 11 //lz标记下传 12 void push_down(int id, int l, int r) { 13 if (lz[id]) { 14 int mid = (l + r) / 2; 15 lz[id * 2] += lz[id]; 16 lz[id * 2 + 1] += lz[id]; 17 tree[id * 2] += 1LL * (mid - l + 1) * lz[id]; 18 tree[id * 2 + 1] += 1LL * (r - mid) * lz[id]; 19 lz[id] = 0; 20 } 21 } 22 23 //左右树信息合并 24 void push_up(int id) { 25 tree[id] = tree[id * 2] + tree[id * 2 + 1]; 26 } 27 // 创建线段树 28 void build(int id, int l, int r) { 29 if (l == r) { 30 cin >> tree[id];//初始化可根据自己的要求来改写; 31 return; 32 } 33 int mid = (l + r) / 2; 34 build(id * 2, l, mid); 35 build(id * 2 + 1, mid + 1, r); 36 push_up(id); 37 } 38 39 // 区间更新,lr为更新范围,LR为线段树范围,add为更新值 40 41 void update(int id, int L, int R, int l, int r, int add) { 42 if (l <= L && r >= R) { 43 lz[id] += 1LL * add; 44 tree[id] += 1LL * (R - L + 1) * add; // 更新方式 45 return; 46 } 47 push_down(id, L, R); 48 int mid = (L + R) / 2; 49 if (mid >= l) update(id * 2, L, mid, l, r, add); 50 if (mid < r) update(id * 2 + 1, mid + 1, R, l, r, add); 51 push_up(id); 52 } 53 // 区间查找 54 ll query(int id, int L, int R, int l, int r) { 55 if (l <= L && r >= R) return tree[id]; 56 push_down(id, L, R); 57 int mid = (L + R) / 2; 58 ll sum = 0; 59 if (mid >= l) sum += query(id * 2, L, mid, l, r); 60 if (mid < r) sum += query(id * 2 + 1, mid + 1, R, l, r); 61 return sum; 62 } 63 64 int main() { 65 int n, m; 66 cin >> n >> m; 67 build(1, 1, n); 68 while (m--) { 69 int ty; 70 cin >> ty; 71 if (ty == 1) { 72 int l, r,d; 73 cin >> l >> r >> d; 74 update(1, 1, n, l, r, d); 75 } 76 else { 77 int l, r; 78 cin >> l >>r; 79 cout << query(1, 1, n, l, r) << endl; 80 } 81 } 82 return 0; 83 }
这个是区间加;
下面这个是涵盖了乘法,根据比对可以知道线段树要改什么地方,怎么改
#include<iostream> #include<string> #define ll long long const int N = 1e5 + 5; int mod; using namespace std; ll tree[N<<2]; // 线段树,可以是对应的结构体 struct node { ll mul, add; }lz[N << 2]; // 延迟标记,也可以是结构体 //lz标记下传 void push_down(int id, int l, int r) { if (lz[id].add!=0||lz[id].mul!=1) { int mid = (l + r) / 2; tree[id * 2] = (tree[id * 2] * lz[id].mul + lz[id].add * (mid - l + 1)) % mod; tree[id * 2 + 1] = (tree[id * 2+1] * lz[id].mul + lz[id].add * (r - mid))%mod; lz[id * 2].mul *= lz[id].mul; lz[id * 2].mul %= mod; lz[id * 2].add = (lz[id].mul * lz[id * 2].add + lz[id].add) % mod; lz[id * 2+1].mul *= lz[id].mul; lz[id * 2 + 1].mul %= mod; lz[id * 2 + 1].add = (lz[id].mul * lz[id * 2 + 1].add + lz[id].add) % mod; lz[id].mul = 1; lz[id].add = 0; } } //左右树信息合并 void push_up(int id) { tree[id] = tree[id * 2] + tree[id * 2 + 1]; } // 创建线段树 void build(int id, int l, int r) { lz[id].add = 0; lz[id].mul = 1; if (l == r) { cin >> tree[id];//初始化可根据自己的要求来改写; return; } int mid = (l + r) / 2; build(id * 2, l, mid); build(id * 2 + 1, mid + 1, r); push_up(id); } // 区间更新,lr为更新范围,LR为线段树范围,add为更新值 void update(int id, int L, int R, int l, int r, node t) { if (l <= L && r >= R) { tree[id] = (1LL * (R - L + 1) * t.add + tree[id] * t.mul) % mod; lz[id].mul *= t.mul; lz[id].mul %= mod; lz[id].add = (lz[id].add * t.mul + t.add) % mod; // 更新方式 return; } push_down(id, L, R); int mid = (L + R) / 2; if (mid >= l) update(id * 2, L, mid, l, r, t); if (mid < r) update(id * 2 + 1, mid + 1, R, l, r, t); push_up(id); } // 区间查找 ll query(int id, int L, int R, int l, int r) { if (l <= L && r >= R) return tree[id]; push_down(id, L, R); int mid = (L + R) / 2; ll sum = 0; if (mid >= l) sum += query(id * 2, L, mid, l, r) % mod; if (mid < r) sum += query(id * 2 + 1, mid + 1, R, l, r) % mod; sum %= mod; return sum; } int main() { int n, m; cin >> n >> m >> mod; build(1, 1, n); while (m--) { int ty; cin >> ty; if (ty == 1||ty==2) { int l, r,d; cin >> l >> r >> d; if(ty==1) update(1, 1, n, l, r, {d,0}); else update(1, 1, n, l, r, {1,d}); } else { int l, r; cin >> l >>r; cout << query(1, 1, n, l, r) << endl; } } return 0; }