区间修改change to,区间查询最小值min
struct segtree
{
struct node
{
int l, r, tag;
int val;
};
vector<node> tr;
segtree(int n1) : tr((n1 + 10) << 2) {}
void build(int root, int l, int r) //根节点为1,范围从1-n
{
tr[root].l = l;
tr[root].r = r;
tr[root].tag = -inf; //修改值若为负数则要修改,tag的值应在修改范围之外
if (l == r)
{
tr[root].val = a[l]; //初始值
return;
}
int mid = (l + r) >> 1;
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
tr[root].val = min(tr[root << 1].val, tr[root << 1 | 1].val);
}
void spread(int p)
{
if (tr[p].tag != -inf)
{
tr[p << 1].val = tr[p].tag;
tr[p << 1 | 1].val = tr[p].tag;
tr[p << 1].tag = tr[p].tag;
tr[p << 1 | 1].tag = tr[p].tag;
tr[p].tag = -inf;
}
}
void update(int root, int l, int r, int x)
{
if (l <= tr[root].l && r >= tr[root].r)
{
tr[root].val = x;
tr[root].tag = x;
return;
}
spread(root);
int mid = (tr[root].l + tr[root].r) >> 1;
if (l <= mid)
update(root << 1, l, r, x);
if (r > mid)
update(root << 1 | 1, l, r, x);
tr[root].val = min(tr[root << 1].val, tr[root << 1 | 1].val);
}
int getmin(int root, int l, int r) //单点更新下的
{
if (l <= tr[root].l && r >= tr[root].r)
return tr[root].val;
spread(root);
int mid = (tr[root].l + tr[root].r) >> 1;
int ans = inf * inf;
if (l <= mid)
ans = min(ans, getmin(root << 1, l, r));
if (r > mid)
ans = min(ans, getmin(root << 1 | 1, l, r));
return ans;
}
};
区间修改change to,区间求和sum
struct segtree
{
struct node
{
int l, r, tag;
int val;
};
vector<node> tr;
segtree(int n1) : tr((n1 + 10) << 2) {}
void build(int root, int l, int r) //根节点为1,范围从1-n
{
tr[root].l = l;
tr[root].r = r;
tr[root].tag = inf; //设置为一个不可能达到的值
if (l == r)
{
tr[root].val = 0; //初始值
return;
}
int mid = (l + r) >> 1;
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
}
void spread(int p)
{
if (tr[p].tag != inf)
{
tr[p << 1].val = tr[p].tag * (tr[p << 1].r - tr[p << 1].l + 1);
tr[p << 1 | 1].val = tr[p].tag * (tr[p << 1 | 1].r - tr[p << 1 | 1].l + 1);
tr[p << 1].tag = tr[p].tag;
tr[p << 1 | 1].tag = tr[p].tag;
tr[p].tag = inf;
}
}
void update(int root, int l, int r, int x)
{
if (l <= tr[root].l && r >= tr[root].r)
{
tr[root].val = x * (tr[root].r - tr[root].l + 1);
tr[root].tag = x;
return;
}
spread(root);
int mid = (tr[root].l + tr[root].r) >> 1;
if (l <= mid)
update(root << 1, l, r, x);
if (r > mid)
update(root << 1 | 1, l, r, x);
tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
}
int getsum(int root, int l, int r) //单点更新下的
{
if (l <= tr[root].l && r >= tr[root].r)
return tr[root].val;
spread(root);
int mid = (tr[root].l + tr[root].r) >> 1;
int ans = 0;
if (l <= mid)
ans = (ans + getsum(root << 1, l, r));
if (r > mid)
ans = (ans + getsum(root << 1 | 1, l, r));
return ans;
}
};
区间加减add,区间求和sum
struct segtree
{
struct node
{
int l, r, tag;
int val;
};
vector<node> tr;
segtree(int n1) : tr((n1 + 10) << 2) {}
void build(int root, int l, int r) //根节点为1,范围从1-n
{
tr[root].l = l;
tr[root].r = r;
tr[root].tag = 0; // add的初始值为0
if (l == r)
{
tr[root].val = 0; //初始值
return;
}
int mid = (l + r) >> 1;
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
}
void spread(int p)
{
if (tr[p].tag != 0)
{
tr[p << 1].val += tr[p].tag * (tr[p << 1].r - tr[p << 1].l + 1);
tr[p << 1 | 1].val += tr[p].tag * (tr[p << 1 | 1].r - tr[p << 1 | 1].l + 1);
tr[p << 1].tag += tr[p].tag;
tr[p << 1 | 1].tag += tr[p].tag;
tr[p].tag = 0;
}
}
void update(int root, int l, int r, int x)
{
if (l <= tr[root].l && r >= tr[root].r)
{
tr[root].val += x * (tr[root].r - tr[root].l + 1);
tr[root].tag += x;
return;
}
spread(root);
int mid = (tr[root].l + tr[root].r) >> 1;
if (l <= mid)
update(root << 1, l, r, x);
if (r > mid)
update(root << 1 | 1, l, r, x);
tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
}
int getsum(int root, int l, int r) //单点更新下的
{
if (l <= tr[root].l && r >= tr[root].r)
return tr[root].val;
spread(root);
int mid = (tr[root].l + tr[root].r) >> 1;
int ans = 0;
if (l <= mid)
ans = (ans + getsum(root << 1, l, r));
if (r > mid)
ans = (ans + getsum(root << 1 | 1, l, r));
return ans;
}
};
区间加减add,区间最小值min
struct segtree
{
struct node
{
int l, r, tag;
int val;
};
vector<node> tr;
segtree(int n1) : tr((n1 + 10) << 2) {}
void build(int root, int l, int r) //根节点为1,范围从1-n
{
tr[root].l = l;
tr[root].r = r;
tr[root].tag = 0; // add的初始值为0
if (l == r)
{
tr[root].val = 0; //初始值
return;
}
int mid = (l + r) >> 1;
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
tr[root].val = min(tr[root << 1].val, tr[root << 1 | 1].val);
}
void spread(int p)
{
if (tr[p].tag != 0)
{
tr[p << 1].val += tr[p].tag;
tr[p << 1 | 1].val += tr[p].tag;
tr[p << 1].tag += tr[p].tag;
tr[p << 1 | 1].tag += tr[p].tag;
tr[p].tag = 0;
}
}
void update(int root, int l, int r, int x)
{
if (l <= tr[root].l && r >= tr[root].r)
{
tr[root].val += x;
tr[root].tag += x;
return;
}
spread(root);
int mid = (tr[root].l + tr[root].r) >> 1;
if (l <= mid)
update(root << 1, l, r, x);
if (r > mid)
update(root << 1 | 1, l, r, x);
tr[root].val = min(tr[root << 1].val, tr[root << 1 | 1].val);
}
int getmin(int root, int l, int r) //单点更新下的
{
if (l <= tr[root].l && r >= tr[root].r)
return tr[root].val;
spread(root);
int mid = (tr[root].l + tr[root].r) >> 1;
int ans = inf * inf;
if (l <= mid)
ans = min(ans, getmin(root << 1, l, r));
if (r > mid)
ans = min(ans, getmin(root << 1 | 1, l, r));
return ans;
}
};
区间加、乘,区间求和(取模)
struct segtree
{
struct node
{
int l, r, val, tag1, tag2;
};
const int mod1; //不取模时可设成ll_max
vector<node> tr;
segtree(int n1, int mo) : mod1(mo), tr((n1 + 10) << 2) {}
void build(int root, int l, int r) //根节点为1,范围从1-n
{
tr[root].l = l;
tr[root].r = r;
tr[root].tag1 = 0; // add的初始值为0
tr[root].tag2 = 1; //乘法初始值为1
if (l == r)
{
tr[root].val = a[l]; //初始值
return;
}
int mid = (l + r) >> 1;
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
tr[root].val = (tr[root << 1].val + tr[root << 1 | 1].val) % mod1;
}
void spread(int p)
{
if (tr[p].tag2 != 1)
{
tr[p << 1].val = (tr[p << 1].val * tr[p].tag2) % mod1;
tr[p << 1 | 1].val = (tr[p << 1 | 1].val * tr[p].tag2) % mod1;
tr[p << 1].tag2 = (tr[p << 1].tag2 * tr[p].tag2) % mod1;
tr[p << 1 | 1].tag2 = (tr[p << 1 | 1].tag2 * tr[p].tag2) % mod1;
tr[p << 1].tag1 = (tr[p << 1].tag1 * tr[p].tag2) % mod1;
tr[p << 1 | 1].tag1 = (tr[p << 1 | 1].tag1 * tr[p].tag2) % mod1;
tr[p].tag2 = 1;
}
if (tr[p].tag1 != 0)
{
tr[p << 1].val = (tr[p << 1].val + tr[p].tag1 * (tr[p << 1].r - tr[p << 1].l + 1)) % mod1;
tr[p << 1 | 1].val = (tr[p << 1 | 1].val + tr[p].tag1 * (tr[p << 1 | 1].r - tr[p << 1 | 1].l + 1)) % mod1;
tr[p << 1].tag1 = (tr[p << 1].tag1 + tr[p].tag1) % mod1;
tr[p << 1 | 1].tag1 = (tr[p << 1 | 1].tag1 + tr[p].tag1) % mod1;
tr[p].tag1 = 0;
}
}
void update(int root, int l, int r, int x, int y)
{
if (tr[root].l >= l && tr[root].r <= r)
{
tr[root].val = (tr[root].val * y) % mod1;
tr[root].val = (tr[root].val + x * (tr[root].r - tr[root].l + 1)) % mod1;
tr[root].tag1 = ((tr[root].tag1 * y) + x) % mod1;
tr[root].tag2 = (tr[root].tag2 * y) % mod1;
return;
}
spread(root);
int mid = (tr[root].r + tr[root].l) >> 1;
if (l <= mid)
update(root << 1, l, r, x, y);
if (r > mid)
update(root << 1 | 1, l, r, x, y);
tr[root].val = (tr[root << 1].val + tr[root << 1 | 1].val) % mod1;
}
int getsum(int root, int l, int r) //单点更新下的
{
if (tr[root].l >= l && tr[root].r <= r)
return tr[root].val % mod1;
spread(root);
int mid = (tr[root].l + tr[root].r) >> 1;
int ans = 0;
if (l <= mid)
ans = (ans + getsum(root << 1, l, r)) % mod1;
if (r > mid)
ans = (ans + getsum(root << 1 | 1, l, r)) % mod1;
return ans;
}
};
单点修改,区间取模,区间求和O(n * logn * loga)
势能线段树:某个值最多能修改常数次,故区间修改时只需判断当前区间内有无需要修改的数,有则暴力修改即可
const int maxn = 100010;
int a[maxn];
struct segtree
{
struct node
{
int l, r, tag;
int val;
};
vector<node> tr;
segtree(int n1) : tr((n1 + 10) << 2) {}
void push_up(int root)
{
tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
tr[root].tag = max(tr[root << 1].tag, tr[root << 1 | 1].tag);
}
void build(int root, int l, int r) //根节点为1,范围从1-n
{
tr[root].l = l;
tr[root].r = r;
if (l == r)
{
tr[root].val = a[l]; //初始值
tr[root].tag = a[l];
return;
}
int mid = (l + r) >> 1;
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
push_up(root);
}
void update1(int root, int l, int r, int mod) //区间取模
{
if (tr[root].l == tr[root].r)
{
tr[root].val %= mod;
tr[root].tag = tr[root].val;
return;
}
int mid = (tr[root].l + tr[root].r) >> 1;
if (l <= mid && tr[root << 1].tag >= mod) //势能线段树修改条件
update1(root << 1, l, r, mod);
if (r > mid && tr[root << 1 | 1].tag >= mod) //势能线段树修改条件
update1(root << 1 | 1, l, r, mod);
push_up(root);
}
void update2(int root, int l, int r, int x) //单点修改
{
if (tr[root].l == tr[root].r)
{
tr[root].val = tr[root].tag = x;
return;
}
int mid = (tr[root].r + tr[root].l) >> 1;
if (l <= mid)
update2(root << 1, l, r, x);
if (r > mid)
update2(root << 1 | 1, l, r, x);
push_up(root);
}
int getsum(int root, int l, int r) //区间求和
{
if (l <= tr[root].l && r >= tr[root].r)
return tr[root].val;
int mid = (tr[root].l + tr[root].r) >> 1;
int ans = 0;
if (l <= mid)
ans = (ans + getsum(root << 1, l, r));
if (r > mid)
ans = (ans + getsum(root << 1 | 1, l, r));
return ans;
}
};