题单链接
https://vjudge.net/article/752
别人的笔记 https://blog.csdn.net/weixin_45799835/article/details/110069469
精选:4
单点修改,区间和查询模板
#include
#include
#include
using namespace std;
template<int maxn>
struct segment_tree {
#define LX(x) ((x)<<1)
#define RX(x) (((x)<<1)|1)
struct node {
int val;
int l, r;
} a[maxn*5+10];
void merge(int x) {
a[x].val = a[LX(x)].val + a[RX(x)].val;
}
void build(int x, int l, int r) {
a[x].l = l;
a[x].r = r;
if (l==r) {
scanf("%d", &a[x].val);
return;
}
build(LX(x), l, (l+r)>>1);
build(RX(x), ((l+r)>>1)+1, r);
merge(x);
}
void modify_add(int x, int pos, int val) {
if (a[x].l == a[x].r) {
a[x].val += val;
return;
}
int lx=LX(x), rx=RX(x);
if (pos <= a[lx].r)
modify_add(lx, pos, val);
if (pos >= a[rx].l)
modify_add(rx, pos, val);
merge(x);
}
int query(int x, int L, int R) {
if (a[x].l>=L && a[x].r<=R) {
return a[x].val;
}
int ret=0;
int lx=LX(x), rx=RX(x);
if (L <= a[lx].r)
ret += query(lx, L, R);
if (R >= a[rx].l)
ret += query(rx, L, R);
return ret;
}
#undef LX
#undef RX
};
int n;
segment_tree<50000> T;
void solve()
{
cin >>n;
T.build(1, 1, n);
string op;
int i, j;
while (1) {
cin >>op;
if (op=="Add") {
cin >>i >>j;
T.modify_add(1, i, j);
}
else if (op=="Sub") {
cin >>i >>j;
T.modify_add(1, i, -j);
}
else if (op=="Query") {
cin >>i >>j;
cout <<T.query(1, i, j) <<'\n';
}
else if (op=="End") {
break;
}
}
}
int main()
{
int ttt;
cin >>ttt;
for (int i=1; i<=ttt; i++) {
cout <<"Case " <<i <<":\n";
solve();
}
return 0;
}
/*
1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End
*/
单点修改,区间最大值查询模板
#include
#include
#include
using namespace std;
template<int maxn>
struct segment_tree {
#define LX(x) ((x)<<1)
#define RX(x) (((x)<<1)|1)
struct node {
int val_max;
int l, r;
} a[maxn*4+10];
void merge(int x) {
a[x].val_max = max(a[LX(x)].val_max, a[RX(x)].val_max);
}
void build(int x, int l, int r) {
a[x].l = l;
a[x].r = r;
if (l==r) {
scanf("%d", &a[x].val_max);
return;
}
build(LX(x), l, (l+r)>>1);
build(RX(x), ((l+r)>>1)+1, r);
merge(x);
}
void modify(int x, int pos, int val) {
if (a[x].l==a[x].r) {
a[x].val_max = val;
return;
}
int lx=LX(x), rx=RX(x);
if (pos <= a[lx].r)
modify(lx, pos, val);
if (pos >= a[rx].l)
modify(rx, pos, val);
merge(x);
}
int query(int x, int L, int R) {
if (L<=a[x].l && a[x].r<=R) {
return a[x].val_max;
}
int lx=LX(x), rx=RX(x);
int ret=0;
if (L<=a[lx].r)
ret = max(ret, query(lx, L, R));
if (R>=a[rx].l)
ret = max(ret, query(rx, L, R));
return ret;
}
#undef LX
#undef RX
};
int n, m;
segment_tree<200005> T;
bool solve()
{
if (scanf("%d%d", &n, &m) != 2)
return false;
T.build(1, 1, n);
while (m--) {
char op[5];
int i, j;
scanf("%s%d%d", op, &i, &j);
if (*op=='Q') {
printf("%d\n", T.query(1, i, j));
}
else {
T.modify(1, i, j);
}
}
return true;
}
int main()
{
while (solve())
;
return 0;
}
区间修改,区间和查询模板
// https://vjudge.net/problem/POJ-3468
#include
#include
using namespace std;
template<typename t_val, int maxn>
struct segment_tree {
#define LX(x) ((x)<<1)
#define RX(x) (((x)<<1)|1)
#define SZ(x) (a[x].r-a[x].l+1)
struct node {
t_val val;
t_val tag;
int l, r;
} a[maxn*4+10];
void merge(int x) {
a[x].val = a[x].tag*SZ(x);
a[x].val += a[LX(x)].val;
a[x].val += a[RX(x)].val;
}
void down_tag(int x) {
int lx=LX(x), rx=RX(x);
a[lx].tag += a[x].tag;
a[lx].val += a[x].tag * SZ(lx);
a[rx].tag += a[x].tag;
a[rx].val += a[x].tag * SZ(rx);
a[x].tag = 0;
}
void build(int x, int l, int r) {
a[x].l = l;
a[x].r = r;
a[x].tag = 0;
if (l==r) {
scanf("%lld", &a[x].val);
return;
}
build(LX(x), l, (l+r)>>1);
build(RX(x), ((l+r)>>1)+1, r);
merge(x);
}
void modify_add(int x, int L, int R, t_val val) {
if (L<=a[x].l && a[x].r<=R) {
a[x].val += val*SZ(x);
a[x].tag += val;
return;
}
const int lx = LX(x), rx=RX(x);
down_tag(x);
if (L<=a[lx].r)
modify_add(lx, L, R, val);
if (R>=a[rx].l)
modify_add(rx, L, R, val);
merge(x);
}
t_val query(int x, int L, int R) {
if (L<=a[x].l && a[x].r<=R) {
return a[x].val;
}
down_tag(x);
t_val ret=0;
int lx=LX(x), rx=RX(x);
if (L<=a[lx].r)
ret += query(lx, L, R);
if (R>=a[rx].l)
ret += query(rx, L, R);
return ret;
}
#undef LX
#undef RX
};
int n, q;
segment_tree<long long, 100005> T;
void solve()
{
cin >>n >>q;
T.build(1, 1, n);
char op[5];
int a, b, c;
while (q--) {
scanf("%s", op);
if (*op=='C') {
scanf("%d%d%d", &a, &b, &c);
T.modify_add(1, a, b, c);
}
else {
scanf("%d%d", &a, &b);
printf("%lld\n", T.query(1, a, b));
}
}
}
int main()
{
solve();
return 0;
}
和 4 一样是线段覆盖,尝试了一下用珂朵莉树。
珂朵莉树资料 https://oi-wiki.org/ds/odt/
#include
#include
using namespace std;
struct Old_Driver_Tree {
struct node_t {
int l, r;
mutable int v;
node_t(const int &l_, const int &r_, const int &v_): l(l_), r(r_), v(v_) {}
bool operator<(const node_t &o) const {return l<o.l;}
};
set<node_t> odt;
int maxn;
void init(int n) {
maxn = n;
odt.clear();
odt.insert(node_t(1, maxn, 1)); // 一开始全是1
}
// 返回指向以 x 为左端点的区间的迭代器
set<node_t>::iterator split(int x) {
if (x>maxn) return odt.end();
auto it = --odt.upper_bound(node_t(x, 0, 0));
if (it->l == x) return it;
int l = it->l, r = it->r, v = it->v;
odt.erase(it);
odt.insert(node_t(l, x-1, v));
return odt.insert(node_t(x, r, v)).first;
}
// 将 [l, r] 区间赋值为 v,会将 set 中该区间包含的所有节点合并为一个节点
// 注意先求 itr,再求 itl。否则 itr 可能会失效
void assign(int l, int r, int v) {
auto itr = split(r+1);
auto itl = split(l);
odt.erase(itl, itr);
odt.insert(node_t(l, r, v));
}
};
Old_Driver_Tree TT;
void solve(int iidd)
{
int n , q, xx, yy, zz;
int ans=0;
scanf("%d%d", &n, &q);
TT.init(n);
while (q--) {
scanf("%d%d%d", &xx, &yy, &zz);
TT.assign(xx, yy, zz);
}
for (auto &i: TT.odt) {
//printf("%d %d %d\n", i.l, i.r, i.v);
ans += (i.r-i.l+1)*i.v;
}
printf("Case %d: The total value of the hook is %d.\n", iidd, ans);
}
int main()
{
int ttt;
scanf("%d", &ttt);
for (int tt=1; tt<=ttt; tt++) {
solve(tt);
}
return 0;
}
/*
1
10
2
1 5 2
5 9 3
*/