随手打打字

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 校门外的树(增强版)

建立两颗线段树,分别维护树的棵树、树+树苗的棵数,最后答案就是:

  1. 树苗数 = 总数(树+树苗棵数) - 树的棵数
  2. 砍掉的树苗数 = 总砍掉的数目 - 砍掉树的数目
#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]简单题

区间翻转,实际上可以合并[线段树]打字练习记录_线段树[线段树]打字练习记录_线段树_02数组,因为一模一样。。。

#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_03的线段树,叶子节点维护乘数,需要乘的时候将当前位置更新为乘数,需要除的时候将该操作的位置更新为[线段树]打字练习记录_#include_03,然后查询直接输出根节点即可。

#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;
}