随手打打字
1.P3372 【模板】线段树 1
裸板子
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int tree[N << 2], lazy[N << 2];
inline void push_up(int rt){ tree[rt] = tree[rt << 1] + tree[rt << 1 | 1]; }
inline void push_down(int rt, int m){
if(lazy[rt]){
lazy[rt << 1] += lazy[rt], lazy[rt << 1 | 1] += lazy[rt];
tree[rt << 1] += lazy[rt] * (m - (m >> 1));
tree[rt << 1 | 1] += lazy[rt] * (m >> 1);
lazy[rt] = 0;
}
}
void build(int rt, int l, int r){
lazy[rt] = 0;
if(l == r){
cin >> tree[rt];
return;
}
int mid = l + r >> 1;
build(rt << 1, l, mid), build(rt << 1 | 1, mid + 1, r);
push_up(rt);
}
void update_part(int rt, int l, int r, int L, int R, int val){
if(l >= L && r <= R){
lazy[rt] += val;
tree[rt] += val * (r - l + 1);
return;
}
push_down(rt, r - l + 1);
int mid = l + r >> 1;
if(mid >= L) update_part(rt << 1, l, mid, L, R, val);
if(mid < R) update_part(rt << 1 | 1, mid + 1, r, L, R, val);
push_up(rt);
}
int query(int rt, int l, int r, int L, int R){
if(l >= L && r <= R) return tree[rt];
push_down(rt, r - l + 1);
int mid = l + r >> 1, ans = 0;
if(mid >= L) ans += query(rt << 1, l, mid, L, R);
if(mid < R) ans += query(rt << 1 | 1, mid + 1, r, L, R);
return ans;
}
inline void solve(){
int n, m; cin >> n >> m;
build(1, 1, n);
while(m--){
int op, x, y, k; cin >> op >> x >> y;
if(op == 1){
cin >> k;
update_part(1, 1, n, x, y, k);
}
else cout << query(1, 1, n, x, y) << endl;
}
}
signed main(){
solve();
return 0;
}
2.P3373 【模板】线段树 2
维护乘法标记和加法标记,注意运算顺序和取模操作。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int MOD = 571373;
int tree[N << 2], lazy_mul[N << 2], lazy_add[N << 2];
inline int binpow(int x, int n, int MOD, int ret = 1){
for(x %= MOD; n; n >>= 1, (x *= x) %= MOD) if(n & 1) (ret *= x) %= MOD;
return ret == 1 ? 0 : ret;
}
inline void push_up(int rt){ tree[rt] = (tree[rt << 1] + tree[rt << 1 | 1]) % MOD; }
inline void push_down(int rt, int m){
lazy_mul[rt << 1] = (lazy_mul[rt << 1] * lazy_mul[rt]) % MOD;
lazy_mul[rt << 1 | 1] = (lazy_mul[rt << 1 | 1] * lazy_mul[rt]) % MOD;
lazy_add[rt << 1] = (lazy_add[rt << 1] * lazy_mul[rt] + lazy_add[rt]) % MOD;
lazy_add[rt << 1 | 1] = (lazy_add[rt << 1 | 1] * lazy_mul[rt] + lazy_add[rt]) % MOD;
tree[rt << 1] = (tree[rt << 1] * lazy_mul[rt] + lazy_add[rt] * (m - (m >> 1))) % MOD;
tree[rt << 1 | 1] = (tree[rt << 1 | 1] * lazy_mul[rt] + lazy_add[rt] * (m >> 1)) % MOD;
lazy_add[rt] = 0, lazy_mul[rt] = 1;
}
void build(int rt, int l, int r){
lazy_add[rt] = 0, lazy_mul[rt] = 1;
if(l == r){
cin >> tree[rt];
return;
}
int mid = l + r >> 1;
build(rt << 1, l, mid), build(rt << 1 | 1, mid + 1, r);
push_up(rt);
}
void update_add(int rt, int l, int r, int L, int R, int val){
if(l >= L && r <= R){
(lazy_add[rt] += val) %= MOD;
(tree[rt] += val * (r - l + 1)) %= MOD;
return;
}
push_down(rt, r - l + 1);
int mid = l + r >> 1;
if(mid >= L) update_add(rt << 1, l, mid, L, R, val);
if(mid < R) update_add(rt << 1 | 1, mid + 1, r, L, R, val);
push_up(rt);
}
void update_mul(int rt, int l, int r, int L, int R, int val){
if(l >= L && r <= R){
(lazy_add[rt] *= val) %= MOD;
(lazy_mul[rt] *= val) %= MOD;
(tree[rt] *= val) %= MOD;
return;
}
push_down(rt, r - l + 1);
int mid = l + r >> 1;
if(mid >= L) update_mul(rt << 1, l, mid, L, R, val);
if(mid < R) update_mul(rt << 1 | 1, mid + 1, r, L, R, val);
push_up(rt);
}
int query(int rt, int l, int r, int L, int R){
if(l >= L && r <= R) return tree[rt];
push_down(rt, r - l + 1);
int mid = l + r >> 1, ans = 0;
if(mid >= L) (ans += query(rt << 1, l, mid, L, R)) %= MOD;
if(mid < R) (ans += query(rt << 1 | 1, mid + 1, r, L, R)) %= MOD;
return ans;
}
inline void solve(){
int n, m; cin >> n >> m >> MOD;
build(1, 1, n);
while(m--){
int op, x, y, k; cin >> op >> x >> y;
if(op == 1){
cin >> k;
update_mul(1, 1, n, x, y, k);
}
else if(op == 2){
cin >> k;
update_add(1, 1, n, x, y, k);
}
else{
cout << query(1, 1, n, x, y) << endl;
}
}
}
signed main(){
ios_base::sync_with_stdio(false); cin.tie(0), cout.tie(0);
solve();
return 0;
}
3.P2023 [AHOI2009] 维护序列
根上题一模一样,继续练习打字
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int tree[N << 2], lazy_mul[N << 2], lazy_add[N << 2], MOD = INT_MAX;
inline void push_up(int rt){ tree[rt] = (tree[rt << 1] + tree[rt << 1 | 1]) % MOD; }
inline void push_down(int rt, int m){
lazy_mul[rt << 1] = (lazy_mul[rt << 1] * lazy_mul[rt]) % MOD;
lazy_mul[rt << 1 | 1] = (lazy_mul[rt << 1 | 1] * lazy_mul[rt]) % MOD;
lazy_add[rt << 1] = (lazy_add[rt << 1] * lazy_mul[rt] + lazy_add[rt]) % MOD;
lazy_add[rt << 1 | 1] = (lazy_add[rt << 1 | 1] * lazy_mul[rt] + lazy_add[rt]) % MOD;
tree[rt << 1] = (tree[rt << 1] * lazy_mul[rt] + lazy_add[rt] * (m - (m >> 1))) % MOD;
tree[rt << 1 | 1] = (tree[rt << 1 | 1] * lazy_mul[rt] + lazy_add[rt] * (m >> 1)) % MOD;
lazy_add[rt] = 0, lazy_mul[rt] = 1;
}
void build(int rt, int l, int r){
lazy_add[rt] = 0, lazy_mul[rt] = 1;
if(l == r){
cin >> tree[rt];
return;
}
int mid = l + r >> 1;
build(rt << 1, l, mid), build(rt << 1 | 1, mid + 1, r);
push_up(rt);
}
void update_mul(int rt, int l, int r, int L, int R, int val){
if(l >= L && r <= R){
(lazy_mul[rt] *= val) %= MOD;
(lazy_add[rt] *= val) %= MOD;
(tree[rt] *= val) %= MOD;
return;
}
push_down(rt, r - l + 1);
int mid = l + r >> 1;
if(mid >= L) update_mul(rt << 1, l, mid, L, R, val);
if(mid < R) update_mul(rt << 1 | 1, mid + 1, r, L, R, val);
push_up(rt);
}
void update_add(int rt, int l, int r, int L, int R, int val){
if(l >= L && r <= R){
(lazy_add[rt] += val) %= MOD;
(tree[rt] += val * (r - l + 1)) %= MOD;
return;
}
push_down(rt, r - l + 1);
int mid = l + r >> 1;
if(mid >= L) update_add(rt << 1, l, mid, L, R, val);
if(mid < R) update_add(rt << 1 | 1, mid + 1, r, L, R, val);
push_up(rt);
}
int query(int rt, int l, int r, int L, int R){
if(l >= L && r <= R) return tree[rt];
push_down(rt, r - l + 1);
int mid = l + r >> 1, ans = 0;
if(mid >= L) (ans += query(rt << 1, l, mid, L, R)) %= MOD;
if(mid < R) (ans += query(rt << 1 | 1, mid + 1, r, L, R)) %= MOD;
return ans;
}
inline void solve(){
int n, p; cin >> n >> MOD;
build(1, 1, n);
int m; cin >> m;
while(m--){
int op, x, y, k; cin >> op >> x >> y;
if(op == 1){
cin >> k;
update_mul(1, 1, n, x, y, k);
}
else if(op == 2){
cin >> k;
update_add(1, 1, n, x, y, k);
}
else cout << query(1, 1, n, x, y) << endl;
}
}
signed main(){
solve();
return 0;
}
4.P1047 [NOIP2005 普及组] 校门外的树
线段树维护清零操作+根节点查询,继续练习打字
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
int tree[N << 2], lazy[N << 2];
inline void push_up(int rt){ tree[rt] = tree[rt << 1] + tree[rt << 1 | 1]; }
inline void push_down(int rt){
if(lazy[rt]) return;
lazy[rt << 1] = lazy[rt], lazy[rt << 1 | 1] = lazy[rt];
tree[rt << 1] = lazy[rt], tree[rt << 1 | 1] = lazy[rt];
lazy[rt] = 1;
}
void build(int rt, int l, int r){
lazy[rt] = 1;
if(l == r){
tree[rt] = 1;
return;
}
int mid = l + r >> 1;
build(rt << 1, l, mid), build(rt << 1 | 1, mid + 1, r);
push_up(rt);
}
void update(int rt, int l, int r, int L, int R){
if(l >= L && r <= R){
lazy[rt] = 0;
tree[rt] = 0;
return;
}
push_down(rt);
int mid = l + r >> 1;
if(mid >= L) update(rt << 1, l, mid, L, R);
if(mid < R) update(rt << 1 | 1, mid + 1, r, L, R);
push_up(rt);
}
inline void solve(){
int n, m; cin >> n >> m; n += 1;
build(1, 1, n);
while(m--){
int u, v; cin >> u >> v;
update(1, 1, n, u + 1, v + 1);
}
cout << tree[1] << endl;
}
signed main(){
solve();
return 0;
}
5.P1276 校门外的树(增强版)
建立两颗线段树,分别维护树的棵树、树+树苗的棵数,最后答案就是:
- 树苗数 = 总数(树+树苗棵数) - 树的棵数
- 砍掉的树苗数 = 总砍掉的数目 - 砍掉树的数目
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int tree[N << 2][2], lazy[N << 2][2], cnt1 = 0, cnt2 = 0;
inline void push_up(int rt, int i){ tree[rt][i] = tree[rt << 1][i] + tree[rt << 1 | 1][i]; }
inline void push_down(int rt, int i, int m){
if(!lazy[rt][i]) return;
else if(lazy[rt][i] == 1){
lazy[rt << 1][i] = lazy[rt << 1 | 1][i] = 1;
tree[rt << 1][i] = (m - (m >> 1)), tree[rt << 1 | 1][i] = (m >> 1);
}
else{
lazy[rt << 1][i] = lazy[rt << 1 | 1][i] = -1;
tree[rt << 1][i] = tree[rt << 1 | 1][i] = 0;
}
lazy[rt][i] = 0;
}
void build(int rt, int l, int r){
lazy[rt][1] = lazy[rt][0] = 0;
if(l == r){
tree[rt][0] = tree[rt][1] = 1;
return;
}
int mid = l + r >> 1;
build(rt << 1, l, mid), build(rt << 1 | 1, mid + 1, r);
push_up(rt, 0), push_up(rt, 1);
}
void CutTree(int rt, int l, int r, int L, int R){
if(l >= L && r <= R){
cnt1 += tree[rt][0], cnt2 += tree[rt][1];
lazy[rt][0] = lazy[rt][1] = -1;
tree[rt][0] = tree[rt][1] = 0;
return;
}
push_down(rt, 0, r - l + 1), push_down(rt, 1, r - l + 1);
int mid = l + r >> 1;
if(mid >= L) CutTree(rt << 1, l, mid, L, R);
if(mid < R) CutTree(rt << 1 | 1, mid + 1, r, L, R);
push_up(rt, 1), push_up(rt, 0);
}
void PlantTree(int rt, int l, int r, int L, int R){
if(l >= L && r <= R){
lazy[rt][1] = 1;
tree[rt][1] = (r - l + 1);
return;
}
push_down(rt, 1, r - l + 1);
int mid = l + r >> 1;
if(mid >= L) PlantTree(rt << 1, l, mid, L, R);
if(mid < R) PlantTree(rt << 1 | 1, mid + 1, r, L, R);
push_up(rt, 1);
}
inline void solve(){
int n, m; cin >> n >> m; n += 1;
build(1, 1, n);
while(m--){
int op, l, r; cin >> op >> l >> r;
if(op == 0) CutTree(1, 1, n, l + 1, r + 1);
else PlantTree(1, 1, n, l + 1, r + 1);
/*DEBUG
cout << "DEBUG " << tree[1][1] << " " << tree[1][0] << endl;
cout << "DEBUG " << cnt2 << " " << cnt1 << endl;*/
}
cout << tree[1][1] - tree[1][0] << endl;
cout << cnt2 - cnt1 << endl;
}
signed main(){
solve();
return 0;
}
6.P1531 I Hate It
单点查询区间修改,ZKW也可写。
#include <bits/stdc++.h>
using namespace std;
#define lson rt << 1, l,
#define rson rt << 1 | 1, mid + 1,
const int N = 2e5 + 10;
int tree[N << 2];
inline void push_up(int rt){ tree[rt] = max(tree[rt << 1], tree[rt << 1 | 1]); }
void build(int rt, int l, int r){
if(l == r){
cin >> tree[rt];
return;
}
int mid = l + r >> 1;
build(lson), build(rson);
push_up(rt);
}
void update(int rt, int l, int r, int pos, int val){
if(l == r){
tree[rt] = max(val, tree[rt]);
return;
}
int mid = l + r >> 1;
if(mid >= pos) update(lson, pos, val);
else update(rson, pos, val);
push_up(rt);
}
int query_part(int rt, int l, int r, int L, int R){
if(l >= L && r <= R) return tree[rt];
int mid = l + r >> 1, ans = 0;
if(mid >= L) ans = max(ans, query_part(lson, L, R));
if(mid < R) ans = max(ans, query_part(rson, L, R));
return ans;
}
inline void solve(){
int n, m; cin >> n >> m;
build(1, 1, n);
while(m--){
char op; int x, y;
cin >> op >> x >> y;
if(op == 'Q') cout << query_part(1, 1, n, x, y) << endl;
else update(1, 1, n, x, y);
}
}
signed main(){
solve();
return 0;
}
7.P5057 [CQOI2006]简单题
区间翻转,实际上可以合并和数组,因为一模一样。。。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int tree[N << 2], lazy[N << 2];
#define lson rt << 1, l,
#define rson rt << 1 | 1, mid + 1,
inline void push_down(int rt){
if(!lazy[rt]) return;
tree[rt << 1] ^= 1, tree[rt << 1 | 1] ^= 1;
lazy[rt << 1] ^= 1, lazy[rt << 1 | 1] ^= 1;
lazy[rt] = 0;
}
void update(int rt, int l, int r, int L, int R){
if(l >= L && r <= R){
tree[rt] ^= 1, lazy[rt] ^= 1;
return;
}
int mid = l + r >> 1;
if(mid >= L) update(lson, L, R);
if(mid < R) update(rson, L, R);
}
int query(int rt, int l, int r, int pos){
if(l == r) return tree[rt];
int mid = l + r >> 1;
push_down(rt);
if(mid >= pos) return query(lson, pos);
else return query(rson, pos);
}
inline void solve(){
int n, m; cin >> n >> m;
while(m--){
int op, x, y; cin >> op >> x;
if(op == 1){
cin >> y;
update(1, 1, n, x, y);
}
else cout << query(1, 1, n, x) << endl;
}
}
signed main(){
solve();
return 0;
}
8.P4588 [TJOI2018]数学计算
建立初始全为的线段树,叶子节点维护乘数,需要乘的时候将当前位置更新为乘数,需要除的时候将该操作的位置更新为,然后查询直接输出根节点即可。
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
const int N = 1e5 + 10;
int tree[N << 2], MOD = 0;
#define ls rt << 1, l,
#define rs rt << 1 | 1, mid + 1,
inline void push_up(int rt){ tree[rt] = (tree[rt << 1] * tree[rt << 1 | 1]) % MOD; }
void build(int rt, int l, int r){
if(l == r){
tree[rt] = 1;
return;
}
int mid = l + r >> 1;
build(ls), build(rs);
push_up(rt);
}
void update(int rt, int l, int r, int pos, int val){
if(l == r){
tree[rt] = val;
return;
}
int mid = l + r >> 1;
if(mid >= pos) update(ls, pos, val);
else update(rs, pos, val);
push_up(rt);
}
int query(int rt, int l, int r, int pos){
if(l == r) return tree[rt];
int mid = l + r >> 1;
if(mid <= pos) return query(ls, pos);
else return query(rs, pos);
}
inline void solve(){
int q; std::cin >> q >> MOD;
build(1, 1, q);
int cnt = 0;
for(int i = 1; i <= q; i++){
int op, m; std::cin >> op >> m;
if(op == 1){
update(1, 1, q, i, m);
std::cout << tree[1] % MOD << endl;
}
else{
update(1, 1, q, m, 1);
std::cout << tree[1] % MOD << endl;
}
}
}
signed main(){
int t = 0; std::cin >> t;
while(t--) solve();
return 0;
}