线段树
区间加 区间和
区间乘法的懒标记优先级高于加法,且会对加法懒标记造成影响
void push_up(node &u,node &l,node &r) {
u.sum = l.sum + r.sum; //
}
void pushup(vector<node> &tr, int u) {
push_up(tr[u],tr[u<<1],tr[u<<1|1]);
}
void push_down(vector<node> &tr,int u) { //
if(tr[u].la != 0) {
tr[u<<1].la += tr[u].la;
tr[u<<1|1].la += tr[u].la;
tr[u<<1].sum += (tr[u<<1].r - tr[u<<1].l + 1) * 1ll * tr[u].la;
tr[u<<1|1].sum += (tr[u<<1|1].r - tr[u<<1|1].l + 1) * 1ll * tr[u].la;
tr[u].la = 0;
}
}
void build(vector<node> &tr, int u, int l, int r,vector<int> &a) {
tr[u].l = l; tr[u].r = r;
if (l == r) {
tr[u] = {l,r,a[l],0}; //
return;
}
int mid = (l + r) >> 1;
build(tr,u << 1,l,mid,a);
build(tr,u << 1 | 1,mid + 1,r,a);
pushup(tr, u);
}
void modify(vector<node> &tr, int u , int L , int R, int k) {
int l = tr[u].l, r = tr[u].r;
if(l >= L && r <= R) { // 目标区间
tr[u].sum += 1ll * (r - l + 1) * k;
tr[u].la += k;
return;
}
int mid = (l + r) >> 1;
push_down(tr,u);
if(L <= mid) modify(tr,u<<1,L,R,k);
if(R > mid) modify(tr,u<<1|1,L,R,k);
pushup(tr,u);
}
node query(vector<node> &tr,int u,int L,int R) {
if(L <= tr[u].l && tr[u].r <= R) return tr[u];
int mid = (tr[u].l + tr[u].r) >> 1;
push_down(tr,u);
if(R <= mid) return query(tr,u << 1,L,R);
else if(L > mid) return query(tr,u << 1 | 1,L,R);
else {
node p,pl,pr;
pl = query(tr,u << 1,L,R);
pr = query(tr,u << 1 | 1,L,R);
push_up(p,pl,pr);
return p;
}
}
区间赋值 等差数列
\(1\ l\ r\ k\) :表示将下标在 \([l , r]\) 区间内的数字替换成 \([k,k+1,…,k+r-l]\)
\(lazy\) 仅表示一个区间最左侧的值 ,通过\(lazy\) 和区间长度 可以得到 \(sum\)
$sum = (lazy + lazy + (len - 1)) / 2 * len $
$sum = \frac{n(a_{1} + a_{n})}{2} $
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
struct node{
int l,r;
ll sum;
ll la;
};
void push_up(node &u,node &l,node &r) {
u.sum = l.sum + r.sum;
}
void pushup(vector<node> &tr, int u) {
push_up(tr[u],tr[u<<1],tr[u<<1|1]);
}
void push_down(vector<node> &tr,int u) {
if(tr[u].la != 0) {
ll len = tr[u<<1].r - tr[u<<1].l + 1;
tr[u<<1].la = tr[u].la;
tr[u<<1].sum = (tr[u].la + tr[u].la + len - 1) * len / 2;
tr[u<<1|1].la = tr[u].la + len;
ll lgt = tr[u<<1|1].r - tr[u<<1|1].l + 1;
tr[u<<1|1].sum = (tr[u<<1|1].la + tr[u<<1|1].la + lgt - 1) * lgt / 2;
tr[u].la = 0;
}
}
void build(vector<node> &tr, int u, int l, int r,vector<int> &a) {
tr[u].l = l; tr[u].r = r;
if (l == r) {
tr[u] = {l,r,a[l],0};
return;
}
int mid = (l + r) >> 1;
build(tr,u << 1,l,mid,a);
build(tr,u << 1 | 1,mid + 1,r,a);
pushup(tr, u);
}
void modify(vector<node> &tr, int u , int L , int R, int k) {
int l = tr[u].l, r = tr[u].r;
if(l >= L && r <= R) { // 目标区间 L,R
tr[u].la = k + (l - L);
tr[u].sum = (tr[u].la + tr[u].la + (r - l) ) * (r - l + 1) / 2;
return;
}
int mid = (l + r) >> 1;
push_down(tr,u);
if(L <= mid) modify(tr,u<<1,L,R,k);
if(R > mid) modify(tr,u<<1|1,L,R,k);
pushup(tr,u);
}
node query(vector<node> &tr,int u,int L,int R) {
if(L <= tr[u].l && tr[u].r <= R) return tr[u];
int mid = (tr[u].l + tr[u].r) >> 1;
push_down(tr,u);
if(R <= mid) return query(tr,u << 1,L,R);
else if(L > mid) return query(tr,u << 1 | 1,L,R);
else {
node p,pl,pr;
pl = query(tr,u << 1,L,R);
pr = query(tr,u << 1 | 1,L,R);
push_up(p,pl,pr);
return p;
}
}
void solve() {
int n,q;
std::cin >> n >> q;
std::vector<int> a(n+1);
std::vector<node> tr(n * 4 + 4);
for(int i = 1; i <= n; i++) std::cin >> a[i];
build(tr,1,1,n,a);
while(q --) {
int op,x,y,k;
std::cin >> op;
if(op == 1) {
std::cin >> x >> y >> k;
modify(tr,1,x,y,k);
}
else {
std::cin >> x >> y;
std::cout << query(tr,1,x,y).sum << '\n';
}
}
return;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int _ = 1;
//std::cin >> _;
while(_ --) {
solve();
}
return 0;
}
区间gcd
给定一个长度为N的数列A,以及M条指令 (N≤5*10^5, M<=10^5),每条指令可能是以下两种之一:
“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。
“Q l r”,表示询问 A[l],A[l+1],…,A[r] 的最大公约数(GCD)。
首先区间\(gcd\) 具有合并性 \(u.d = gcd(l.d,r.d)\)
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
ll gcd(ll a,ll b) {
return b == 0 ? a : gcd(b,a%b);
}
struct node{
int l,r;
ll d;
};
void push_up(node &u,node &l,node &r) {
u.d = gcd(l.d,r.d);
}
void pushup(vector<node> &tr, int u) {
push_up(tr[u],tr[u<<1],tr[u<<1|1]);
}
void build(vector<node> &tr, int u, int l, int r,vector<int> &a) {
tr[u].l = l; tr[u].r = r;
if (l == r) {
tr[u] = {l,r,a[l]};
return;
}
int mid = (l + r) >> 1;
build(tr,u << 1,l,mid,a);
build(tr,u << 1 | 1,mid + 1,r,a);
pushup(tr, u);
}
node query(vector<node> &tr,int u,int L,int R) {
if(L <= tr[u].l && tr[u].r <= R) return tr[u];
int mid = (tr[u].l + tr[u].r) >> 1;
if(R <= mid) return query(tr,u << 1,L,R);
else if(L > mid) return query(tr,u << 1 | 1,L,R);
else {
node p,pl,pr;
pl = query(tr,u << 1,L,R);
pr = query(tr,u << 1 | 1,L,R);
push_up(p,pl,pr);
return p;
}
}
void solve() {
int n,q;
std::cin >> n >> q;
std::vector<int> a(n+1);
std::vector<node> tr(n * 4 + 4);
for(int i = 1; i <= n; i++) std::cin >> a[i];
build(tr,1,1,n,a);
while(q --) {
int x,y;
std::cin >> x >> y;
std::cout << query(tr,1,x,y).d << '\n';
}
return;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int _ = 1;
//std::cin >> _;
while(_ --) {
solve();
}
return 0;
}
但是\(gcd(a_l+v,a_{l+1}+v,...,a_r + v)\) 与 \(gcd(a_l,a_{l+1},...,a_r)\) 无关,
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
ll gcd(ll a,ll b) {
return b == 0 ? a : gcd(b,a%b);
}
struct node{
ll l,r;
ll sum;
ll d;
};
void push_up(node &u,node &l,node &r) {
u.sum = l.sum + r.sum;
u.d = gcd(l.d,r.d);
}
void pushup(vector<node> &tr, int u) {
push_up(tr[u],tr[u<<1],tr[u<<1|1]);
}
void build(vector<node> &tr, int u, int l, int r,vector<ll> &a) {
tr[u].l = l; tr[u].r = r;
if (l == r) {
tr[u] = {l,r,a[l],a[l]};
return;
}
int mid = (l + r) >> 1;
build(tr,u << 1,l,mid,a);
build(tr,u << 1 | 1,mid + 1,r,a);
pushup(tr, u);
}
void modify(vector<node> &tr, int u , int L , int R, ll k) {
int l = tr[u].l, r = tr[u].r;
if(l >= L && r <= R) { // 目标区间
tr[u].sum += k;
tr[u].d += k;
return;
}
int mid = (l + r) >> 1;
//push_down(tr,u);
if(L <= mid) modify(tr,u<<1,L,R,k);
if(R > mid) modify(tr,u<<1|1,L,R,k);
pushup(tr,u);
}
node query(vector<node> &tr,int u,int L,int R) {
if(L <= tr[u].l && tr[u].r <= R) return tr[u];
int mid = (tr[u].l + tr[u].r) >> 1;
//push_down(tr,u);
if(R <= mid) return query(tr,u << 1,L,R);
else if(L > mid) return query(tr,u << 1 | 1,L,R);
else {
node p,pl,pr;
pl = query(tr,u << 1,L,R);
pr = query(tr,u << 1 | 1,L,R);
push_up(p,pl,pr);
return p;
}
}
void solve() {
int n,q;
std::cin >> n >> q;
std::vector<ll> a(n+1),b(n+1);
std::vector<node> tr(n * 3);
for(int i = 1; i <= n; i++) std::cin >> a[i];
for(int i = 1; i <= n; i++) {
b[i] = a[i] - a[i-1];
}
build(tr,1,1,n,b);
while(q --) {
char op;
int x,y; ll k;
std::cin >> op;
if(op == 'C') {
std::cin >> x >> y >> k;
modify(tr,1,x,x,k);
if(y + 1 <= n) {
modify(tr,1,y+1,y+1,-k);
}
}
else {
std::cin >> x >> y;
ll A1 = 0 , A2 = 0;
if(x <= n) A1 = query(tr,1,1,x).sum;
if(x + 1 <= y) A2 = query(tr,1,x+1,y).d;
std::cout << std::abs( gcd(A1,A2) ) << '\n';
}
}
return;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int _ = 1;
//std::cin >> _;
while(_ --) {
solve();
}
return 0;
}
区间最大连续子段和
\(max_{x \leq l \leq r \leq y}({\sum_{r_i=l}^{r}A[i]})\)
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
struct node{
int l,r;
int sum;
int lmx,rmx,mx;
};
void push_up(node &u,node &l,node &r) {
u.sum = l.sum + r.sum;
u.lmx = max(l.lmx, l.sum + r.lmx);
u.rmx = max(r.rmx, r.sum + l.rmx);
u.mx = max({l.mx,r.mx,l.rmx + r.lmx});
}
void pushup(vector<node> &tr, int u) {
push_up(tr[u],tr[u<<1],tr[u<<1|1]);
}
void build(vector<node> &tr, int u, int l, int r,vector<int> &a) {
tr[u].l = l; tr[u].r = r;
if (l == r) {
tr[u] = {l,r,a[l],a[l],a[l],a[l]};
return;
}
int mid = (l + r) >> 1;
build(tr,u << 1,l,mid,a);
build(tr,u << 1 | 1,mid + 1,r,a);
pushup(tr, u);
}
void modify(vector<node> &tr, int u , int L , int R, int k) {
int l = tr[u].l, r = tr[u].r;
if(l >= L && r <= R) { // 目标区间
tr[u].sum = k;
tr[u].lmx = k;
tr[u].rmx = k;
tr[u].mx = k;
return;
}
int mid = (l + r) >> 1;
//push_down(tr,u);
if(L <= mid) modify(tr,u<<1,L,R,k);
if(R > mid) modify(tr,u<<1|1,L,R,k);
pushup(tr,u);
}
node query(vector<node> &tr,int u,int L,int R) {
if(L <= tr[u].l && tr[u].r <= R) return tr[u];
int mid = (tr[u].l + tr[u].r) >> 1;
//push_down(tr,u);
if(R <= mid) return query(tr,u << 1,L,R);
else if(L > mid) return query(tr,u << 1 | 1,L,R);
else {
node p,pl,pr;
pl = query(tr,u << 1,L,R);
pr = query(tr,u << 1 | 1,L,R);
push_up(p,pl,pr);
return p;
}
}
void solve() {
int n,q;
std::cin >> n >> q;
std::vector<int> a(n+1);
std::vector<node> tr(n * 4 + 4);
for(int i = 1; i <= n; i++) std::cin >> a[i];
build(tr,1,1,n,a);
while(q --) {
int op,x,y; int k;
std::cin >> op;
if(op == 1) {
std::cin >> x >> y;
if(x > y) swap(x,y);
std::cout << query(tr,1,x,y).mx << '\n';
}
else {
std::cin >> x >> k;
modify(tr,1,x,x,k);
}
}
return;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int _ = 1;
//std::cin >> _;
while(_ --) {
solve();
}
return 0;
}
标签:std,node,int,线段,tr,sum,ll
From: https://www.cnblogs.com/Elgina/p/18385565