模板 - 线段树
区间修改线段树:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lt ls, l, m
#define rt rs, m + 1, r
#define ls (o<<1)
#define rs (o<<1|1)
const int MAXM = 100000 + 5;
ll a[MAXM];
ll st[MAXM * 4], lazy[MAXM * 4];
inline void PushUp(int o) {
st[o] = st[ls] + st[rs];
}
inline void PushDown(int o, int l, int r) {
if(lazy[o]) {
lazy[ls] += lazy[o];
lazy[rs] += lazy[o];
int m = l + r >> 1;
st[ls] += lazy[o] * (m - l + 1);
st[rs] += lazy[o] * (r - m);
lazy[o] = 0;
}
}
void Build(int o, int l, int r) {
if(l == r)
st[o] = a[l];
else {
int m = l + r >> 1;
Build(lt);
Build(rt);
PushUp(o);
}
lazy[o] = 0;
}
void Update(int o, int l, int r, int ql, int qr, ll v) {
if(ql <= l && r <= qr) {
lazy[o] += v;
st[o] += v * (r - l + 1);
return;
} else {
PushDown(o, l, r);
int m = l + r >> 1;
if(ql <= m)
Update(lt, ql, qr, v);
if(qr >= m + 1)
Update(rt, ql, qr, v);
PushUp(o);
}
}
ll Query(int o, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) {
return st[o];
} else {
PushDown(o, l, r);
int m = l + r >> 1;
ll res = 0;
if(ql <= m)
res = res + Query(lt, ql, qr);
if(qr >= m + 1)
res = res + Query(rt, ql, qr);
return res;
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
Build(1,1,n);
int op, x, y, k;
while(m--) {
scanf("%d%d%d", &op, &x, &y);
if(op == 1) {
scanf("%d", &k);
Update(1, 1, n, x, y, k);
} else {
printf("%lld\n", Query(1, 1, n, x, y));
}
}
return 0;
}
单点修改线段树:
const int MAXM=100000;
int a[MAXM+5];
int st[(MAXM<<2)+5];
inline void push_up(int o) {
st[o]=st[o<<1]+st[o<<1|1];
}
void build(int o,int l,int r) {
if(l==r){
st[o]=a[l];
}
else {
int m=(l+r)>>1;
build(o<<1,l,m);
build(o<<1|1,m+1,r);
push_up(o);
}
}
void update(int o,int l,int r,int x,int v) {
if(l==r) {
st[o]=v;
return;
} else {
int m=(l+r)>>1;
if(x<=m)
update(o<<1,l,m,x,v);
else if(x>=m+1)
update(o<<1|1,m+1,r,x,v);
push_up(o);
}
}
int query(int o,int l,int r,int a,int b) {
if(a<=l&&r<=b) {
return st[o];
} else {
int m=(l+r)>>1;
int ans=0;
if(a<=m)
ans=query(o<<1,l,m,a,b);
if(b>=m+1)
ans+=query(o<<1|1,m+1,r,a,b);
return ans;
}
}
需要注意lazy的更新顺序的区间修改线段树:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXM = 100000 + 5;
int a[MAXM];
ll sum[MAXM << 2], add[MAXM << 2], mul[MAXM << 2];
int mod;
inline void push_up(int o) {
sum[o] = (sum[o << 1] + sum[o << 1 | 1]) % mod;
}
inline void push_down(int o, int l, int r) {
if(mul[o] != 1) {
mul[o << 1] = mul[o << 1] * mul[o] % mod;
mul[o << 1 | 1] = mul[o << 1 | 1] * mul[o] % mod;
add[o << 1] = add[o << 1] * mul[o] % mod;
add[o << 1 | 1] = add[o << 1 | 1] * mul[o] % mod;
sum[o << 1] = sum[o << 1] * mul[o] % mod;
sum[o << 1 | 1] = sum[o << 1 | 1] * mul[o] % mod;
mul[o] = 1;
}
if(add[o] != 0) {
add[o << 1] = (add[o << 1] + add[o]) % mod;
add[o << 1 | 1] = (add[o << 1 | 1] + add[o]) % mod;
int m = (l + r) >> 1;
sum[o << 1] = (sum[o << 1] + add[o] * (m - l + 1)) % mod;
sum[o << 1 | 1] = (sum[o << 1 | 1] + add[o] * (r - m) ) % mod;
add[o] = 0;
}
}
void build(int o, int l, int r) {
if(l == r)
sum[o] = a[l];
else {
int m = (l + r) >> 1;
build(o << 1, l, m);
build(o << 1 | 1, m + 1, r);
push_up(o);
}
mul[o] = 1, add[o] = 0;
}
void update_add(int o, int l, int r, int a, int b, ll v) {
if(a <= l && r <= b) {
add[o] = (add[o] + v) % mod;
sum[o] = (sum[o] + v * (r - l + 1) % mod) % mod;
return;
} else {
push_down(o, l, r);
int m = (l + r) >> 1;
if(a <= m)
update_add(o << 1, l, m, a, b, v);
if(b >= m + 1)
update_add(o << 1 | 1, m + 1, r, a, b, v);
push_up(o);
}
}
void update_mul(int o, int l, int r, int a, int b, ll v) {
if(a <= l && r <= b) {
mul[o] = mul[o] * v % mod;
add[o] = add[o] * v % mod;
sum[o] = sum[o] * v % mod;
return;
} else {
push_down(o, l, r);
int m = (l + r) >> 1;
if(a <= m)
update_mul(o << 1, l, m, a, b, v);
if(b >= m + 1)
update_mul(o << 1 | 1, m + 1, r, a, b, v);
push_up(o);
}
}
ll query(int o, int l, int r, int a, int b) {
if(a <= l && r <= b) {
return sum[o];
} else {
push_down(o, l, r);
int m = (l + r) >> 1;
ll ans = 0;
if(a <= m)
ans = query(o << 1, l, m, a, b);
if(b >= m + 1)
ans = (ans + query(o << 1 | 1, m + 1, r, a, b)) % mod;
return ans;
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n, m;
scanf("%d%d%d", &n, &m, &mod);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
build(1, 1, n);
for(int i = 1; i <= m; ++i) {
int op, x, y;
scanf("%d%d%d", &op, &x, &y);
if(op == 1) {
int k;
scanf("%d", &k);
update_mul(1, 1, n, x, y, k);
} else if(op == 2) {
int k;
scanf("%d", &k);
update_add(1, 1, n, x, y, k);
} else {
printf("%lld\n", query(1, 1, n, x, y));
}
}
}
lazy标记互相影响的线段树,直接强制下推标记就不用这么多破事。但是要注意叶子是不能下推标记的。
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e6;
const int MAXLOGAI = 4;
int a[MAXN + 5];
int st[MAXN * 4 + 5][MAXLOGAI];
char lazy[MAXN * 4 + 5][MAXLOGAI];
inline void PushUp(int o) {
for(int id = 0; id < MAXLOGAI; ++id)
st[o][id] = st[o << 1][id] + st[o << 1 | 1][id];
}
inline void PushDown(int o, int l, int r) {
//op=1 ^
//op=2 |
//op=3 &
for(int id = 0; id < MAXLOGAI; ++id) {
if(lazy[o][id]) {
int mid = l + r >> 1;
if(lazy[o][id] == 1) {
if(lazy[o << 1][id] == 0) {
st[o << 1][id] = (mid - l + 1) - st[o << 1][id];
lazy[o << 1][id] = 1;
} else if(lazy[o << 1][id] == 1) {
st[o << 1][id] = (mid - l + 1) - st[o << 1][id];
lazy[o << 1][id] = 0;
} else if(lazy[o << 1][id] == 2) {
st[o << 1][id] = 0;
lazy[o << 1][id] = 3;
} else if(lazy[o << 1][id] == 3) {
st[o << 1][id] = (mid - l + 1);
lazy[o << 1][id] = 2;
}
if(lazy[o << 1 | 1][id] == 0) {
st[o << 1 | 1][id] = (r - (mid + 1) + 1) - st[o << 1 | 1][id];
lazy[o << 1 | 1][id] = 1;
} else if(lazy[o << 1 | 1][id] == 1) {
st[o << 1 | 1][id] = (r - (mid + 1) + 1) - st[o << 1 | 1][id];
lazy[o << 1 | 1][id] = 0;
} else if(lazy[o << 1 | 1][id] == 2) {
st[o << 1 | 1][id] = 0;
lazy[o << 1 | 1][id] = 3;
} else if(lazy[o << 1 | 1][id] == 3) {
st[o << 1 | 1][id] = (r - (mid + 1) + 1);
lazy[o << 1 | 1][id] = 2;
}
} else if(lazy[o][id] == 2) {
st[o << 1][id] = (mid - l + 1);
lazy[o << 1][id] = 2;
st[o << 1 | 1][id] = (r - (mid + 1) + 1);
lazy[o << 1 | 1][id] = 2;
} else {
st[o << 1][id] = 0;
lazy[o << 1][id] = 3;
st[o << 1 | 1][id] = 0;
lazy[o << 1 | 1][id] = 3;
}
lazy[o][id] = 0;
}
}
}
void Build(int o, int l, int r) {
for(int id = 0; id < MAXLOGAI; ++id)
lazy[o][id] = 0;
if(l == r) {
for(int id = 0; id < MAXLOGAI; ++id)
st[o][id] = (a[l] & (1 << id)) ? 1 : 0;
} else {
int mid = l + r >> 1;
Build(o << 1, l, mid);
Build(o << 1 | 1, mid + 1, r);
PushUp(o);
}
}
void Update(int o, int l, int r, int ql, int qr, int op, int x) {
//op=1 ^
//op=2 |
//op=3 &
if(l != r)
PushDown(o, l, r);
if(ql <= l && r <= qr) {
if(op == 1) {
for(int id = 0; id < MAXLOGAI; ++id) {
if(x & (1 << id)) {
st[o][id] = (r - l + 1) - st[o][id];
lazy[o][id] = op;
}
}
} else if(op == 2) {
for(int id = 0; id < MAXLOGAI; ++id) {
if(x & (1 << id)) {
st[o][id] = (r - l + 1);
lazy[o][id] = op;
}
}
} else {
for(int id = 0; id < MAXLOGAI; ++id) {
if(!(x & (1 << id))) {
st[o][id] = 0;
lazy[o][id] = op;
}
}
}
} else {
int mid = l + r >> 1;
if(ql <= mid)
Update(o << 1, l, mid, ql, qr, op, x);
if(qr >= mid + 1)
Update(o << 1 | 1, mid + 1, r, ql, qr, op, x);
PushUp(o);
}
}
ll Query(int o, int l, int r, int ql, int qr) {
if(l != r)
PushDown(o, l, r);
if(ql <= l && r <= qr) {
ll res = 0;
for(int id = 0; id < MAXLOGAI; ++id)
res += 1ll * (1 << id) * (st[o][id]);
return res;
} else {
ll res = 0;
int mid = l + r >> 1;
if(ql <= mid)
res += Query(o << 1, l, mid, ql, qr);
if(qr >= mid + 1)
res += Query(o << 1 | 1, mid + 1, r, ql, qr);
return res;
}
}
int main() {
#ifdef localll
freopen("lyz.in", "r", stdin);
#endif // local
int T, n, m;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
Build(1, 1, n);
for(int i = 1; i <= m; ++i) {
char ops[10];
int l, r, x;
scanf("%s", ops);
if(ops[0] == 'S') {
scanf("%d%d", &l, &r);
++l, ++r;
printf("%lld\n", Query(1, 1, n, l, r));
} else {
scanf("%d%d%d", &x, &l, &r);
++l, ++r;
if(ops[0] == 'X') {
Update(1, 1, n, l, r, 1, x);
} else if(ops[0] == 'O') {
Update(1, 1, n, l, r, 2, x);
} else if(ops[0] == 'A') {
Update(1, 1, n, l, r, 3, x);
}
}
}
}
}