# Segment tree training

### P3372 [template] segment tree 1 - New Ecology of computer science education in Luogu (luogu.com.cn)

Interval modification + interval query (board questions)

```#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long ll;
const int N = 1e5 + 50;
int n, m;
ll a[N];

struct Tr{
int l, r;
ll sum, lazy;
}tr[N * 4];

void pushup(int u)
{
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}

void pushdown(int u)
{
ll lazy = tr[u].lazy;
if(lazy)
{
tr[u << 1].lazy += lazy;
tr[u << 1 | 1].lazy += lazy;
tr[u].lazy = 0;
tr[u << 1].sum += (tr[u << 1].r - tr[u << 1].l + 1) * lazy;
tr[u << 1 | 1].sum += (tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1) * lazy;
}
}

void build(int u, int l, int r)
{
tr[u] = {l, r};
if(l == r)
{
tr[u].sum = a[l];
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}

void change(int u, int l, int r, int k)
{
if(l <= tr[u].l && tr[u].r <= r)
{
tr[u].lazy += (ll)k;
tr[u].sum += (ll)(tr[u].r - tr[u].l + 1) * k;
return;
}
pushdown(u);
int mid = (tr[u].l + tr[u].r) >> 1;
if(l <= mid) change(u << 1, l, r, k);
if(r > mid) change(u << 1 | 1, l, r, k);
pushup(u);
}

ll query(int u, int l, int r)
{
if(l <= tr[u].l && tr[u].r <= r)
{
return tr[u].sum;
}
pushdown(u);
int mid = (tr[u].l + tr[u].r) >> 1;
ll ans = 0;
if(l <= mid) ans += query(u << 1, l, r);
if(r > mid) ans += query(u << 1 | 1, l, r);
return ans;
}

int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
build(1, 1, n);
while(m --)
{
int op, l, r, k;
scanf("%d", &op);
if(op == 1)
{
scanf("%d%d%d", &l, &r, &k);
change(1, l, r, k);
}
else
{
scanf("%d%d", &l, &r);
ll ans = query(1, l, r);
printf("%lld\n", ans);
}
}

return 0;
}
```

### P3373 [template] segment tree 2 - New Ecology of computer science education in Luogu (luogu.com.cn)

Lazy markers for addition and multiplication

Pay attention to the order and the missing points in the notes

```#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long ll;
const int N = 1e5 + 50;
int n, m, mod;
ll a[N];

struct Tr{
int l, r;
ll alazy, mlazy, sum;
}tr[N * 4];

void pushup(int u)
{
tr[u].sum = (tr[u << 1].sum + tr[u << 1 | 1].sum) % mod;
}

void pushdown(int u)
{
ll mlazy = tr[u].mlazy, alazy = tr[u].alazy;
tr[u << 1].mlazy = tr[u << 1].mlazy * mlazy % mod;
tr[u << 1 | 1].mlazy = tr[u << 1 | 1].mlazy * mlazy % mod;
tr[u << 1].alazy = (tr[u << 1].alazy * mlazy % mod + alazy) % mod; // alazy change needs to be correct
tr[u << 1 | 1].alazy = (tr[u << 1 | 1].alazy * mlazy % mod + alazy) % mod;
tr[u << 1].sum = (tr[u << 1].sum * mlazy % mod + (tr[u << 1].r - tr[u << 1].l + 1) * alazy % mod) % mod;
tr[u << 1 | 1].sum = (tr[u << 1 | 1].sum * mlazy % mod + (tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1) * alazy % mod) % mod;
tr[u].alazy = 0;
tr[u].mlazy = 1;
}

void build(int u, int l, int r)
{
tr[u] = {l, r, 0, 1, 0};
if(l == r)
{
tr[u].sum = a[l];
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}

void add(int u, int l, int r, int k)
{
if(l <= tr[u].l && tr[u].r <= r)
{
tr[u].alazy = (tr[u].alazy + k) % mod;
tr[u].sum = (tr[u].sum + (ll)k * (tr[u].r - tr[u].l + 1) % mod) % mod; // Remember to drive long long
return;
}
pushdown(u);
int mid = (tr[u].l + tr[u].r) >> 1;
if(l <= mid) add(u << 1, l, r, k);
if(r > mid) add(u << 1 | 1, l, r, k);
pushup(u);
}

void mul(int u, int l, int r, int k)
{
if(l <= tr[u].l && tr[u].r <= r)
{
tr[u].alazy = tr[u].alazy * k % mod; // This place also needs to be changed
tr[u].mlazy = (tr[u].mlazy * k) % mod;
tr[u].sum = (tr[u].sum * k) % mod;
return;
}
pushdown(u);
int mid = (tr[u].l + tr[u].r) >> 1;
if(l <= mid) mul(u << 1, l, r, k);
if(r > mid) mul(u << 1 | 1, l, r, k);
pushup(u);
}

ll query(int u, int l, int r)
{
if(l <= tr[u].l && tr[u].r <= r)
{
return tr[u].sum;
}
pushdown(u);
int mid = (tr[u].l + tr[u].r) >> 1;
ll ans = 0;
if(l <= mid) ans += query(u << 1, l, r);
if(r > mid) ans = (ans + query(u << 1 | 1, l, r)) % mod;
return ans;
}

int main()
{
scanf("%d%d%d", &n, &m, &mod);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
build(1, 1, n);
while(m --)
{
int op, l, r, k;
scanf("%d", &op);
if(op == 1)
{
scanf("%d%d%d", &l, &r, &k);
mul(1, l, r, k);
}
else if(op == 2)
{
scanf("%d%d%d", &l, &r, &k);
}
else {
scanf("%d%d", &l, &r);
ll ans = query(1, l, r);
printf("%lld\n", ans);
}
}

return 0;
}
```

### P5490 [template] scan line - New Ecology of computer science education in Luogu (luogu.com.cn)

Scan line template question

```#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn = 1e6 + 10;
int N, cnt = 0;
ll int x1, x2, y1, y2, X[maxn << 1];
struct scanline{
ll l, r, h;
int mark;//Save weights
bool operator <(const scanline &te)const{
return h  < te.h;
}
}line[maxn << 1];

struct tree{
int l, r, sum;
//sum: the number of times it has been completely covered
//len: the truncated length of the interval
ll len;
}st[maxn << 2];

void build(int o, int l, int r){
st[o].l	= l, st[o].r = r;
st[o].len = 0;
st[o].sum = 0;
if(l == r)return;
int mid = (l + r) >> 1;
build(o << 1, l, mid);
build(o << 1|1, mid + 1, r);
}
void pushup(int o){
int l = st[o].l, r = st[o].r;
if(st[o].sum)st[o].len = X[r + 1] - X[l];//Has been overwritten, update length
else{st[o].len = st[o << 1].len + st[o << 1 |1].len;}
}
void change(int o, ll L, ll R, int c){
int l = st[o].l, r = st[o].r;
//l. R represents the range of o, and l and R mean the interval to be modified
if( X[r + 1] <= L || R <= X[l] )return;
//When the right interval + 1 is less than the left interval,
if(L <= X[l] && X[r + 1] <= R){
st[o].sum += c;
pushup(o);
return;
}
change(o << 1, L, R, c);
change(o << 1 | 1, L, R, c);
pushup(o);
}
int main(){
scanf("%d",&N);
for(int i = 1; i <= N; i++){
cin>>x1>>y1>>x2>>y2;
X[2 * i - 1] = x1, X[2 * i] = x2;
line[2 * i - 1] = (scanline){ x1, x2, y1, 1};
line[2 * i] = (scanline){ x1, x2, y2, -1};
}
N = N << 1;
sort(line + 1, line + N +1);
sort(X + 1, X + N + 1);
int tot = unique(X + 1, X + N + 1) - (X + 1);
build(1, 1 , tot - 1);
//The correspondence of the right endpoint has been modified. We use
//[1,tot - 1] describes [x[1],x[tot]]
ll ans = 0;
for(int i = 1; i < N; i++){
change(1, line[i].l,line[i].r,line[i].mark);
ans += st[1].len *(line[i + 1].h - line[i].h);
}
cout<<ans;
}
```

### [P4588 TJOI2018] mathematical computing - New Ecology of computer science education in Luogu (luogu.com.cn)

Potential energy line segment tree

Taking time as the axis, we establish a segment tree. Leaf nodes maintain the multiplier of the operation time, and non leaf nodes maintain the multiplier of the operation time

Then, for each multiplication, make a single point modification, modify the position of the operation time to the multiplier, and finally output tr[1]

Each time you divide, change the multiplier of the queried operation position to 11. Last output tr[1]

```#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 60;
int T, q, m;

struct node{
int l, r;
ll ans;
}tr[MAXN * 4];

void pushup(int u)
{
tr[u].ans = tr[u << 1].ans * tr[u << 1 | 1].ans % m;
}

void build(int u, int l, int r)
{
tr[u] = {l, r, 1};
if(l == r)
{
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}

void change(int u, int l, int r, int cnt, int val)
{
if(tr[u].l == tr[u].r)
{
tr[u].ans = val;
return;
}
int mid = (tr[u].l + tr[u].r) >> 1;
if(cnt <= mid) change(u << 1, l, r, cnt, val);
else change(u << 1 | 1, l, r, cnt, val);
pushup(u);
}

int main()
{
scanf("%d", &T);
while(T--){
scanf("%d%d", &q, &m);
build(1, 1, q);
for(int i = 1; i <= q; i++)
{
int op, x;
scanf("%d%d", &op, &x);
if(op == 1) {
change(1, 1, q, i, x);
printf("%lld\n", tr[1].ans);
}
else {
change(1, 1, q, x, 1);
printf("%lld\n", tr[1].ans);
}
}
}
return 0;
}
```

### P1502 stars in window - Luogu | new ecology of Computer Science Education (luogu.com.cn)

Scan line naked question

### CF920F SUM and REPLACE - New Ecology of computer science education in Luogu (luogu.com.cn)

Give a length of 3 ⋅ 1 0 5 3⋅10^5 3 ⋅ 105 array ( a i ≤ 106 ) (a_i≤106) (ai ≤ 106), yes 3 ⋅ 1 0 5 3⋅10^5 3 ⋅ 105 queries, each query gives an interval[ l , r l,r l. R] [l, R], there are two operations:

1 l r l r lr: Set[ l , r l,r l. Replace all numbers in R] [l, R] interval with its divisors
2 l r l r lr: Seek[ l , r l,r l. R] [l, R] interval sum

For the potential energy line segment tree, a number can be changed into 2 with a few times, so you only need to mark whether it is all 2 or 1 in each interval of the line segment tree. If so, skip directly

Therefore, you only need to maintain the maximum value of the interval. If it is less than 2, you can skip that interval directly.

```#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long ll;
const int N = 3e5 + 50, M = 1e6 + 60;
int n, m;
int a[N], f[M];

void init()
{
for(int i = 1; i <= M - 20; i++) f[i] = 1;
for(int i = 2; i <= M - 20; i++)
{
for(int j = i; j <= M - 20; j += i) f[j]++;
}
}

struct Tr{
int l, r;
ll sum, mx;
}tr[N * 4];

void pushup(int u)
{
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
tr[u].mx = max(tr[u << 1].mx, tr[u << 1 | 1].mx);
}

void build(int u, int l, int r)
{
tr[u] = {l, r};
if(l == r)
{
tr[u].sum = tr[u].mx = a[l];
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}

void change(int u, int l, int r)
{
if(tr[u].mx <= 2) return;
if(tr[u].l == tr[u].r && l <= tr[u].l && tr[u].r <= r)
{
int t = tr[u].sum;
tr[u].sum = tr[u].mx = f[t];
return;
}
int mid = (tr[u].l + tr[u].r) >> 1;
if(l <= mid) change(u << 1, l, r);
if(r > mid) change(u << 1 | 1, l, r);
pushup(u);
}

ll query(int u, int l, int r)
{
if(l <= tr[u].l && tr[u].r <= r)
{
return tr[u].sum;
}
int mid = (tr[u].l + tr[u].r) >> 1;
ll ans = 0;
if(l <= mid) ans += query(u << 1, l, r);
if(r > mid) ans += query(u << 1 | 1, l, r);
return ans;
}

int main()
{
init();

scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
build(1, 1, n);
while(m --)
{
int op, l, r;
scanf("%d%d%d", &op, &l, &r);
if(op == 1)
{
change(1, l, r);
}
else {
ll ans = query(1, l, r);
printf("%lld\n", ans);
}
}

return 0;
}
```

### D-delusion set_ Niuke practice competition 90 (nowcoder.com)

There are n repeatable sets at the beginning. At the beginning, each set has a number and m operations.

Quant l r x: add a number x to each set numbered l ∼ r.
Ask l r: ask if you can take three numbers from the set of l ∼ r so that they can form a triangle as the side length (that is, the sum of the minimum two is greater than the maximum).
Enter Description:

The first line contains two integers n,m ( 1 ≤ n , m ≤ 1 0 5 ) (1≤n,m≤10^5) (1≤n,m≤105).
The next row of n numbers represents the initial number in each set a i a_i ai​.
Next m lines, each representing an operation.
Ensure that the number added in the operation and the first number are positive integers and do not exceed 1 0 9 10^9 109 and the query interval is legal (1 ≤ l ≤ r ≤ n)

Output Description:

For each Ask operation, one line is output to indicate the answer. If YES, YES is output. Otherwise, NO is output.

analysis:

Conclusion: when all the numbers in the sequence are Fibonacci numbers, any three numbers can not form a triangle

You can tell by typing the table, 1 0 9 10^9 The number of Fibonacci within 109 does not exceed 45
The segment tree maintains the number of each position in the interval. Open n vector s to record all the numbers of each position. When querying an interval, first query in the segment tree[ l , r l,r l. How many numbers are there in R] [l, R]. If more than 45, it will directly return yes. If less than 3, it will return No. otherwise, it will be violently l , r l,r l. Enumeration lookup in vector of R

Posted on Fri, 12 Nov 2021 09:27:14 -0500 by XxDeadmanxX