一个简单的整数问题
例题 一个简单的整数问题
思路
板子题,不同的线段树代码各个函数都会有点区别,下文列出区间求和线段树代码。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 200;
struct node {
int l, r;
ll sum, lazy;
}st[N * 4];
int n, m, a[N];
void pushup(int id) {
st[id].sum = st[id << 1].sum + st[id << 1 | 1].sum;
}
void pushdown(int id) {
node &root = st[id], &left = st[id << 1], &right = st[id << 1 | 1];
if (!root.lazy)return ;
left.lazy += root.lazy;
right.lazy += root.lazy;
left.sum += (left.r - left.l + 1) * root.lazy;
right.sum += (right.r - right.l + 1) * root.lazy;
root.lazy = 0;
}
void build(int l = 1, int r = n, int id = 1) {
if (l == r) st[id] = {l, r, a[l], 0};
else {
st[id] = {l, r};
int mid = l + r >> 1;
build(l, mid, id << 1);
build(mid + 1, r, id << 1 | 1);
pushup(id);
}
}
ll queryRange(int l, int r, int id = 1) {
int s = st[id].l, e = st[id].r;
if (l <= s && e <= r) return st[id].sum;
ll res = 0;
int mid = s + e >> 1;
pushdown(id);
if (l <= mid) res += queryRange(l, r, id << 1);
if (r >= mid + 1) res += queryRange(l, r, id << 1 | 1);
return res;
}
void updateRange(int l, int r, int d, int id = 1) {
int s = st[id].l, e = st[id].r;
if (l <= s && e <= r) {
st[id].lazy += d;
st[id].sum += (e - s + 1) * d;
}
else {
pushdown(id);
int mid = s + e >> 1;
if (l <= mid) updateRange(l, r, d, id << 1);
if (r >= mid + 1) updateRange(l, r, d, id << 1 | 1);
pushup(id);
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
build();
while (m--) {
char op;
cin >> op;
if (op == 'Q') {
int l, r;
cin >> l >> r;
cout << queryRange(l, r) << '\n';
}
else {
int l, r, d;
cin >> l >> r >> d;
updateRange(l, r, d);
}
}
return 0;
}
最大数
例题最大数
思路
单点更新,只需要pushup,不需要pushdown
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2 * 1e5 + 200;
struct node {
int s, e, max;
}st[N * 4];
int n, m, p, a;
void pushup(int id) {
st[id].max = max(st[id << 1].max, st[id << 1 | 1].max);
}
void build(int s, int e, int id = 1) {
if (s == e) st[id] = {s, e, 0};
else {
st[id] = {s, e};
int mid = s + e >> 1;
build(s, mid, id << 1);
build(mid + 1, e, id << 1 | 1);
pushup(id);
}
}
int que(int l, int r, int id = 1){
int s = st[id].s, e = st[id].e;
if (l <= s && e <= r){
return st[id].max;
}
else {
int res = 0;
int mid = s + e >> 1;
if (l <= mid) res = que(l, r, id << 1);
if (r > mid) res = max(res, que(l, r, id << 1 | 1));
return res;
}
}
void update(int p, int x, int id = 1) {
int s = st[id].s, e = st[id].e;
if (p == s && p == e) {
st[id].max = x;
}
else {
int mid = s + e >> 1;
if (p <= mid) update(p, x, id << 1);
else update(p, x, id << 1 | 1);
pushup(id);
}
}
int main() {
cin >> m >> p;
build(1, m);
while (m--) {
char op; cin >> op;
if (op == 'Q'){
int x; cin >> x;
a = que(n - x + 1, n);
cout << a << '\n';
}
else {
int t; cin >> t;
n++;
update(n, ((ll)t + a) % p);
}
}
return 0;
}
你能回答这些问题吗
例题你能回答这些问题吗
思路
最大连续字段和=max(左儿子的最大连续子段和,右儿子的最大连续子段和,跨越中间的某个连续子段和)
给node除了定义开始、结束位置之外,还需要ls(左端点开始的最大连续子段和),rs(右端点开始的最大连续子段和),ts(最大连续子段和),sum(总和)
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 200;
struct node {
int s, e, ls, rs, ts, sum;
}st[N * 4];
int n, m, a[N];
void pushup(node &p, node &l, node &r) {
p.ls = max(l.ls, l.sum + r.ls);
p.rs = max(r.rs, r.sum + l.rs);
p.ts = max({l.ts, r.ts, l.rs + r.ls});
p.sum = l.sum + r.sum;
}
void pushup(int id) {
pushup(st[id], st[id << 1], st[id << 1 | 1]);
}
void build(int s = 1, int e = n, int id = 1) {
if (s == e) st[id] = {s, e, a[s], a[s], a[s], a[s]};
else {
st[id] = {s, e};
int mid = s + e >> 1;
build(s, mid, id << 1);
build(mid + 1, e, id << 1 | 1);
pushup(id);
}
}
node que(int l, int r, int id = 1) {
int s = st[id].s, e = st[id].e;
if (l <= s && e <= r) return st[id];
int mid = s + e >> 1;
if (r <= mid) return que(l, r, id << 1);
else if (l > mid) return que(l, r, id << 1 | 1);
else {
node root, left = que(l, r, id << 1), right = que(l, r, id << 1 | 1);
pushup(root, left, right);
return root;
}
}
void update(int p, int x, int id = 1) {
int s = st[id].s, e = st[id].e;
if (s == e && s == p) st[id] = {s, e, x, x, x, x};
else {
int mid = s + e >> 1;
if (p <= mid) update(p, x, id << 1);
else update(p, x, id << 1 | 1);
pushup(id);
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
build();
while (m--) {
int op, x, y; cin >> op >> x >> y;
if (op == 1) {
if (x > y) swap(x, y);
int res = que(x, y).ts;
cout << res << '\n';
}
else {
update(x, y);
}
}
return 0;
}