Part 0
头文件
#include<bits/stdc++.h>
using namespace std;
int main(){
return 0;
}
快读版
#include<bits/stdc++.h>
using namespace std;
int read(){int ans = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){ans *= 10;ans += ch - '0';ch = getchar();}return ans * f;}
void write(int x){if(x < 0){putchar('-');write(-x);return;}else if(x < 10){putchar(x + '0');}else if(x >= 10){write(x / 10);putchar(x % 10 + '0');}}
int main(){
return 0;
}
快读
void read(int &ans){
ans = 0;
int f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
ans *= 10;
ans += ch - '0';
ch = getchar();
}
}
void write(int x){
if(x < 0){
putchar('-');
write(-x);
return;
}
else if(x < 10){
putchar(x + '0');
}
else if(x >= 10){
write(x / 10);
putchar(x % 10 + '0');
}
}
头文件
#include<bits/stdc++.h>
using namespace std;
int main(){
return 0;
}
快读版
#include<bits/stdc++.h>
using namespace std;
int read(){int ans = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){ans *= 10;ans += ch - '0';ch = getchar();}return ans * f;}
void write(int x){if(x < 0){putchar('-');write(-x);return;}else if(x < 10){putchar(x + '0');}else if(x >= 10){write(x / 10);putchar(x % 10 + '0');}}
int main(){
return 0;
}
快读
void read(int &ans){
ans = 0;
int f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
ans *= 10;
ans += ch - '0';
ch = getchar();
}
}
void write(int x){
if(x < 0){
putchar('-');
write(-x);
return;
}
else if(x < 10){
putchar(x + '0');
}
else if(x >= 10){
write(x / 10);
putchar(x % 10 + '0');
}
}
Part 1 图论
建图
const int N = 1e5 + 10;
#define Son for(int i = G.hd[u], v = G.e[i].to, w = G.e[i].w; i; i = G.e[i].nt, v = G.e[i].to, w = G.e[i].w)
#define PII pair<int, int>
struct edge{
int nt, to, w;
};
struct Graph{
int hd[N], cnt;
edge e[N * 2];
Graph(){
memset(hd, 0, sizeof(hd));
cnt = 0;
}
void add(int x, int y){
e[++cnt].nt = hd[x];
hd[x] = cnt;
e[cnt].to = y;
}
void add(int x, int y, int z){
e[++cnt].nt = hd[x];
hd[x] = cnt;
e[cnt].to = y;
e[cnt].w = z;
}
}G;
const int N = 1e5 + 10;
#define Son for(int i = G.hd[u], v = G.e[i].to, w = G.e[i].w; i; i = G.e[i].nt, v = G.e[i].to, w = G.e[i].w)
#define PII pair<int, int>
struct edge{int nt, to, w;};
struct Graph{
int hd[N], cnt;edge e[N * 2];
Graph(){memset(hd, 0, sizeof(hd));cnt = 0;}
void add(int x, int y){e[++cnt].nt = hd[x];hd[x] = cnt;e[cnt].to = y;}
void add(int x, int y, int z){e[++cnt].nt = hd[x];hd[x] = cnt;e[cnt].to = y;e[cnt].w = z;}
}G;
倍增LCA
int f[N][32], dep[N];
void dfs(int u, int fa){
Son{
if(v == fa) continue;
f[v][0] = u;
dep[v] = dep[u] + 1;
dfs(v, u);
}
}
int LCA(int x, int y){
if(dep[x] < dep[y]) swap(x, y);
for(int i = 30; i >= 0; i--){
if(dep[f[x][i]] > dep[y]){
x = f[x][i];
}
}
if(dep[x] != dep[y]) x = f[x][0];
if(x == y){
return x;
}
for(int i = 30; i >= 0; i--){
if(f[x][i] != f[y][i]){
x = f[x][i], y = f[y][i];
}
}
return f[y][0];
}
int main(){
for(int i = 1; i <= 30; i++){
for(int j = 1; j <= n; j++){
f[j][i] = f[f[j][i - 1]][i - 1];
}
}
return 0;
}
树链剖分
int son[N], siz[N], top[N], dep[N];
int f[N];
int dfn[N], L[N], R[N], cntl;
void dfs1(int u, int F){
siz[u] = 1;
Son{
if(v == F) continue;
dep[v] = dep[u] + 1;
f[v] = u;
dfs1(v, u);
if(siz[v] > siz[son[u]] || son[u] == 0) son[u] = v;
siz[u] += siz[v];
}
}
void dfs2(int u, int F, int tp){
dfn[++cntl] = u;
L[u] = cntl;
top[u] = tp;
if(son[u]) dfs2(son[u], u, tp);
Son{
if(v == F || v == son[u]) continue;
dfs2(v, u, v);
}
R[u] = cntl;
}
int ask(int x, int y){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = f[top[x]], top[x] = top[x];
}
if(dep[x] > dep[y]) swap(x, y);
}
建图
const int N = 1e5 + 10;
#define Son for(int i = G.hd[u], v = G.e[i].to, w = G.e[i].w; i; i = G.e[i].nt, v = G.e[i].to, w = G.e[i].w)
#define PII pair<int, int>
struct edge{
int nt, to, w;
};
struct Graph{
int hd[N], cnt;
edge e[N * 2];
Graph(){
memset(hd, 0, sizeof(hd));
cnt = 0;
}
void add(int x, int y){
e[++cnt].nt = hd[x];
hd[x] = cnt;
e[cnt].to = y;
}
void add(int x, int y, int z){
e[++cnt].nt = hd[x];
hd[x] = cnt;
e[cnt].to = y;
e[cnt].w = z;
}
}G;
const int N = 1e5 + 10;
#define Son for(int i = G.hd[u], v = G.e[i].to, w = G.e[i].w; i; i = G.e[i].nt, v = G.e[i].to, w = G.e[i].w)
#define PII pair<int, int>
struct edge{int nt, to, w;};
struct Graph{
int hd[N], cnt;edge e[N * 2];
Graph(){memset(hd, 0, sizeof(hd));cnt = 0;}
void add(int x, int y){e[++cnt].nt = hd[x];hd[x] = cnt;e[cnt].to = y;}
void add(int x, int y, int z){e[++cnt].nt = hd[x];hd[x] = cnt;e[cnt].to = y;e[cnt].w = z;}
}G;
倍增LCA
int f[N][32], dep[N];
void dfs(int u, int fa){
Son{
if(v == fa) continue;
f[v][0] = u;
dep[v] = dep[u] + 1;
dfs(v, u);
}
}
int LCA(int x, int y){
if(dep[x] < dep[y]) swap(x, y);
for(int i = 30; i >= 0; i--){
if(dep[f[x][i]] > dep[y]){
x = f[x][i];
}
}
if(dep[x] != dep[y]) x = f[x][0];
if(x == y){
return x;
}
for(int i = 30; i >= 0; i--){
if(f[x][i] != f[y][i]){
x = f[x][i], y = f[y][i];
}
}
return f[y][0];
}
int main(){
for(int i = 1; i <= 30; i++){
for(int j = 1; j <= n; j++){
f[j][i] = f[f[j][i - 1]][i - 1];
}
}
return 0;
}
树链剖分
int son[N], siz[N], top[N], dep[N];
int f[N];
int dfn[N], L[N], R[N], cntl;
void dfs1(int u, int F){
siz[u] = 1;
Son{
if(v == F) continue;
dep[v] = dep[u] + 1;
f[v] = u;
dfs1(v, u);
if(siz[v] > siz[son[u]] || son[u] == 0) son[u] = v;
siz[u] += siz[v];
}
}
void dfs2(int u, int F, int tp){
dfn[++cntl] = u;
L[u] = cntl;
top[u] = tp;
if(son[u]) dfs2(son[u], u, tp);
Son{
if(v == F || v == son[u]) continue;
dfs2(v, u, v);
}
R[u] = cntl;
}
int ask(int x, int y){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = f[top[x]], top[x] = top[x];
}
if(dep[x] > dep[y]) swap(x, y);
}
Part 3 数论
快速幂
int ksm(int a, int b, int p){
int ans = 1;
a %= p;
while(b){
if(b & 1){
(ans *= a) %= p;
}
(a *= a) %= p;
b >>= 1;
}
return ans % p;
}
高精度运算
struct gjd{
int n, a[N];
gjd(){
n = 0;
for(int i = 0; i < N; i++){
a[i] = 0;
}
}
};
gjd operator+(gjd a, gjd b){
gjd c;
c.n = max(a.n, b.n);
for(long long i = 1; i <= c.n; i++){
c.a[i] += a.a[i] + b.a[i];
if(c.a[i] >= 10){
c.a[i + 1]++;
}
c.a[i] %= 10;
}
if(c.a[c.n + 1] != 0){
c.n++;
}
return c;
}
gjd operator*(gjd a, int b){
gjd c;
c.n = a.n;
for(int i = 1; i <= c.n; i++){
c.a[i] = a.a[i] * b;
}
for(int i = 1; i <= c.n; i++){
c.a[i + 1] += c.a[i] / 10;
c.a[i] %= 10;
}
while(c.a[c.n + 1] != 0){
c.n++;
c.a[c.n + 1] += c.a[c.n] / 10;
c.a[c.n] %= 10;
}
return c;
}
gjd readgjd(){
gjd c;
char s[N];
scanf("%s", s + 1);
c.n = strlen(s + 1);
for(long long i = 1; i <= c.n; i++){
c.a[c.n - i + 1] = s[i] ^ 48;
}
return c;
}
void print(gjd c){
for(long long i = c.n; i >= 1; i--){
printf("%d", c.a[i]);
}
}
快速幂
int ksm(int a, int b, int p){
int ans = 1;
a %= p;
while(b){
if(b & 1){
(ans *= a) %= p;
}
(a *= a) %= p;
b >>= 1;
}
return ans % p;
}
高精度运算
struct gjd{
int n, a[N];
gjd(){
n = 0;
for(int i = 0; i < N; i++){
a[i] = 0;
}
}
};
gjd operator+(gjd a, gjd b){
gjd c;
c.n = max(a.n, b.n);
for(long long i = 1; i <= c.n; i++){
c.a[i] += a.a[i] + b.a[i];
if(c.a[i] >= 10){
c.a[i + 1]++;
}
c.a[i] %= 10;
}
if(c.a[c.n + 1] != 0){
c.n++;
}
return c;
}
gjd operator*(gjd a, int b){
gjd c;
c.n = a.n;
for(int i = 1; i <= c.n; i++){
c.a[i] = a.a[i] * b;
}
for(int i = 1; i <= c.n; i++){
c.a[i + 1] += c.a[i] / 10;
c.a[i] %= 10;
}
while(c.a[c.n + 1] != 0){
c.n++;
c.a[c.n + 1] += c.a[c.n] / 10;
c.a[c.n] %= 10;
}
return c;
}
gjd readgjd(){
gjd c;
char s[N];
scanf("%s", s + 1);
c.n = strlen(s + 1);
for(long long i = 1; i <= c.n; i++){
c.a[c.n - i + 1] = s[i] ^ 48;
}
return c;
}
void print(gjd c){
for(long long i = c.n; i >= 1; i--){
printf("%d", c.a[i]);
}
}
Part 4 数据结构
树状数组
struct BIT{
int sum[N];
BIT(){
memset(sum, 0, sizeof(sum));
}
int lobit(int x){
return x & -x;
}
void add(int x, int y){
while(x <= n){
sum[x] += y;
x += lobit(x);
}
}
int ask(int x){
int ans = 0;
while(x >= 1){
ans += sum[x];
x -= lobit(x);
}
return ans;
}
}a;
线段树(区间加,区间和)
struct STree{
int sum[N * 4], la[N * 4];
void put_down(int l, int r, int rt){
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
sum[Lson] += la[rt] * (Mid - l + 1);
la[Lson] += la[rt];
sum[Rson] += la[rt] * (r - Mid);
la[Rson] += la[rt];
la[rt] = 0;
}
void build(int l, int r, int rt){
if(l == r){
scanf("%lld", &sum[rt]);
return;
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
build(l, Mid, Lson), build(Mid + 1, r, Rson);
sum[rt] = sum[Lson] + sum[Rson];
}
void add(int l, int r, int rt, int x, int y, int z){
if(l > y || r < x) return;
if(l >= x && r <= y){
sum[rt] += z * (r - l + 1);
la[rt] += z;
return;
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
put_down(l, r, rt);
add(l, Mid, Lson, x, y, z), add(Mid + 1, r, Rson, x, y, z);
sum[rt] = sum[Lson] + sum[Rson];
}
int ask(int l, int r, int rt, int x, int y){
if(l > y || r < x) return 0;
if(l >= x && r <= y){
return sum[rt];
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
put_down(l, r, rt);
return ask(l, Mid, Lson, x, y) + ask(Mid + 1, r, Rson, x, y);
}
}a;
线段树(区间加,区间覆盖,区间和,区间最大值)
struct STree{
int sum[N * 4], la[N * 4], smax[N * 4], cola[N * 4], bj[N * 4];
void put_down(int l, int r, int rt){
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
if(bj[rt]){
sum[Lson] = cola[rt] * (Mid - l + 1);
smax[Lson] = cola[rt];
bj[Lson] = 1, cola[Lson] = cola[rt];
la[Lson] = 0;
sum[Rson] = cola[rt] * (r - Mid);
smax[Rson] = cola[rt];
bj[Rson] = 1, cola[Rson] = cola[rt];
la[Rson] = 0;
cola[rt] = 0;
bj[rt] = 0;
}
sum[Lson] += la[rt] * (Mid - l + 1);
smax[Lson] += la[rt];
la[Lson] += la[rt];
sum[Rson] += la[rt] * (r - Mid);
smax[Rson] += la[rt];
la[Rson] += la[rt];
la[rt] = 0;
}
void build(int l, int r, int rt){
bj[rt] = 0;
if(l == r){
scanf("%lld", &sum[rt]);
smax[rt] = sum[rt];
la[rt] = 0;
cola[rt] = 0;
return;
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
build(l, Mid, Lson), build(Mid + 1, r, Rson);
sum[rt] = sum[Lson] + sum[Rson];
smax[rt] = max(smax[Lson], smax[Rson]);
}
void add(int l, int r, int rt, int x, int y, int z){
if(l >= x && r <= y){
sum[rt] += z * (r - l + 1);
smax[rt] += z;
la[rt] += z;
return;
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
put_down(l, r, rt);
if(x <= Mid) add(l, Mid, Lson, x, y, z);
if(y > Mid) add(Mid + 1, r, Rson, x, y, z);
sum[rt] = sum[Lson] + sum[Rson];
smax[rt] = max(smax[Lson], smax[Rson]);
}
int ask(int l, int r, int rt, int x, int y){
if(l >= x && r <= y){
return sum[rt];
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
put_down(l, r, rt);
int ans = 0;
if(x <= Mid) ans += ask(l, Mid, Lson, x, y);
if(y > Mid) ans += ask(Mid + 1, r, Rson, x, y);
return ans;
}
int Max(int l, int r, int rt, int x, int y){
if(l >= x && r <= y){
return smax[rt];
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
put_down(l, r, rt);
int ans = -1e18;
if(x <= Mid) ans = max(ans, Max(l, Mid, Lson, x, y));
if(y > Mid) ans = max(ans, Max(Mid + 1, r, Rson, x, y));
return ans;
}
void cover(int l, int r, int rt, int x, int y, int z){
if(l >= x && r <= y){
sum[rt] = z * (r - l + 1);
cola[rt] = z;
smax[rt] = z;
bj[rt] = 1;
la[rt] = 0;
return;
}
put_down(l, r, rt);
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
if(x <= Mid) cover(l, Mid, Lson, x, y, z);
if(y > Mid) cover(Mid + 1, r, Rson, x, y, z);
sum[rt] = sum[Lson] + sum[Rson];
smax[rt] = max(smax[Lson], smax[Rson]);
}
}a;
权值线段树
[普通平衡树](https://www.luogu.com.cn/problem/P3369
struct STree{
int sum[N * 30], Ls[N * 30], Rs[N * 30], cnt = 1;
void update(int l, int r, int rt){
sum[rt] = sum[Ls[rt]] + sum[Rs[rt]];
}
void add(int l, int r, int &rt, int x, int y){
if(!rt) rt = ++cnt;
if(l == r){
sum[rt] += y;
return;
}
int Mid = (l + r) >> 1;
if(x <= Mid) add(l, Mid, Ls[rt], x, y);
else add(Mid + 1, r, Rs[rt], x, y);
update(l, r, rt);
}
int ask(int l, int r, int rt, int x, int y){
if(x <= l && r <= y){
return sum[rt];
}
int ans = 0;
int Mid = (l + r) >> 1;
if(x <= Mid) ans += ask(l, Mid, Ls[rt], x, y);
if(y > Mid) ans += ask(Mid + 1, r, Rs[rt], x, y);
return ans;
}
int FoMax(int l, int r, int rt){
if(l == r) return l;
int Mid = (l + r) >> 1;
if(sum[Rs[rt]]) return FoMax(Mid + 1, r, Rs[rt]);
else return FoMax(l, Mid, Ls[rt]);
}
int FoMin(int l, int r, int rt){
if(l == r) return l;
int Mid = (l + r) >> 1;
if(sum[Ls[rt]]) return FoMin(l, Mid, Ls[rt]);
else return FoMin(Mid + 1, r, Rs[rt]);
}
int Max(int l, int r, int rt, int x){
int Mid = (l + r) >> 1;
if(r < x){
if(sum[rt]){
return FoMax(l, r, rt);
}
else{
return 0;
}
}
if(x > Mid + 1 && sum[Rs[rt]]){
int ans = Max(Mid + 1, r, Rs[rt], x);
if(ans) return ans;
}
return Max(l, Mid, Ls[rt], x);
}
int Min(int l, int r, int rt, int x){
int Mid = (l + r) >> 1;
if(l > x){
if(sum[rt]){
return FoMin(l, r, rt);
}
else{
return 0;
}
}
if(x <= Mid && sum[Ls[rt]]){
int ans = Min(l, Mid, Ls[rt], x);
if(ans) return ans;
}
return Min(Mid + 1, r, Rs[rt], x);
}
int kth(int l, int r, int rt, int x){
if(l == r){
return l;
}
int Mid = (l + r) >> 1;
if(x <= sum[Ls[rt]]){
return kth(l, Mid, Ls[rt], x);
}
else{
return kth(Mid + 1, r, Rs[rt], x - sum[Ls[rt]]);
}
}
}a;
线段树合并
struct STree{
int sum[M], Ls[M], Rs[M], cnt;
int mx[M], k[M];
void update(int l, int r, int rt){
sum[rt] = sum[Ls[rt]] + sum[Rs[rt]];
mx[rt] = max(mx[Ls[rt]], mx[Rs[rt]]);
k[rt] = mx[Ls[rt]] >= mx[Rs[rt]] ? k[Ls[rt]] : k[Rs[rt]];
}
void add(int l, int r, int &rt, int x, int y){
if(!rt) rt = ++cnt;
if(l == r){
sum[rt] += y;
mx[rt] += y;
k[rt] = l;
return;
}
int Mid = (l + r) >> 1;
if(x <= Mid) add(l, Mid, Ls[rt], x, y);
else add(Mid + 1, r, Rs[rt], x, y);
update(l, r, rt);
}
int ask(int l, int r, int rt, int x, int y){
if(x <= l && r <= y){
return sum[rt];
}
int ans = 0;
int Mid = (l + r) >> 1;
if(x <= Mid) ans += ask(l, Mid, Ls[rt], x, y);
if(y > Mid) ans += ask(Mid + 1, r, Rs[rt], x, y);
return ans;
}
int aks(int l, int r, int rt1, int rt2){
if(!rt1) return rt2;
if(!rt2) return rt1;
if(l == r){
sum[rt1] += sum[rt2];
mx[rt1] += mx[rt2];
if(mx[rt1]) k[rt1] = l;
else k[rt1] = 0;
return rt1;
}
int Mid = (l + r) >> 1;
Ls[rt1] = aks(l, Mid, Ls[rt1], Ls[rt2]);
Rs[rt1] = aks(Mid + 1, r, Rs[rt1], Rs[rt2]);
update(l, r, rt1);
return rt1;
}
int Max(int l, int r, int rt){
return k[rt];
}
}a;
可持久化线段树(静态区间第k小)
struct STree{
int sum[N * 32], L[N * 32], R[N * 32], cnt;
void update(int rt){
sum[rt] = sum[L[rt]] + sum[R[rt]];
}
void build(int &rt, int l, int r, int x){
if(!rt) rt = ++cnt;
if(l == r){
sum[rt]++;
return;
}
int mid = (l + r) >> 1;
if(x <= mid) build(L[rt], l, mid, x);
if(x > mid) build(R[rt], mid + 1, r, x);
update(rt);
}
void add(int p, int &q, int l, int r, int x){
if(!q) q = ++cnt;
if(l == r){
sum[q] = sum[p] + 1;
return;
}
int mid = (l + r) >> 1;
if(x <= mid){
R[q] = R[p];
add(L[p], L[q], l, mid, x);
}
if(x > mid){
L[q] = L[p];
add(R[p], R[q], mid + 1, r, x);
}
update(q);
}
int ask(int p, int q, int l, int r, int x){
if(l == r) return l;
int mid = (l + r) >> 1;
int cntl = sum[L[q]] - sum[L[p]];
if(cntl >= x){
return ask(L[p], L[q], l, mid, x);
}
else{
return ask(R[p], R[q], mid + 1, r, x - cntl);
}
}
}S;
可持久化线段树(动态区间第k小)
struct STree{
int sum[N * 441], L[N * 441], R[N * 441], cnt;
int ask(int l, int r, int k){
if(l == r) return l;
int cntk = 0;
for(int i = 1; i <= cntx; i++)
cntk -= sum[L[cx[i]]];
for(int i = 1; i <= cnty; i++)
cntk += sum[L[cy[i]]];
int mid = (l + r) >> 1;
if(cntk >= k){
for(int i = 1; i <= cntx; i++)
cx[i] = L[cx[i]];
for(int i = 1; i <= cnty; i++)
cy[i] = L[cy[i]];
return ask(l, mid, k);
}
else{
for(int i = 1; i <= cntx; i++)
cx[i] = R[cx[i]];
for(int i = 1; i <= cnty; i++)
cy[i] = R[cy[i]];
return ask(mid + 1, r, k - cntk);
}
}
void add(int &rt, int l, int r, int x, int y){
if(!rt) rt = ++cnt;
sum[rt] += y;
if(l == r){
return;
}
int mid = (l + r) >> 1;
if(x <= mid){
add(L[rt], l, mid, x, y);
}
else{
add(R[rt], mid + 1, r, x, y);
}
}
}S;
树状数组
struct BIT{
int sum[N];
BIT(){
memset(sum, 0, sizeof(sum));
}
int lobit(int x){
return x & -x;
}
void add(int x, int y){
while(x <= n){
sum[x] += y;
x += lobit(x);
}
}
int ask(int x){
int ans = 0;
while(x >= 1){
ans += sum[x];
x -= lobit(x);
}
return ans;
}
}a;
线段树(区间加,区间和)
struct STree{
int sum[N * 4], la[N * 4];
void put_down(int l, int r, int rt){
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
sum[Lson] += la[rt] * (Mid - l + 1);
la[Lson] += la[rt];
sum[Rson] += la[rt] * (r - Mid);
la[Rson] += la[rt];
la[rt] = 0;
}
void build(int l, int r, int rt){
if(l == r){
scanf("%lld", &sum[rt]);
return;
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
build(l, Mid, Lson), build(Mid + 1, r, Rson);
sum[rt] = sum[Lson] + sum[Rson];
}
void add(int l, int r, int rt, int x, int y, int z){
if(l > y || r < x) return;
if(l >= x && r <= y){
sum[rt] += z * (r - l + 1);
la[rt] += z;
return;
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
put_down(l, r, rt);
add(l, Mid, Lson, x, y, z), add(Mid + 1, r, Rson, x, y, z);
sum[rt] = sum[Lson] + sum[Rson];
}
int ask(int l, int r, int rt, int x, int y){
if(l > y || r < x) return 0;
if(l >= x && r <= y){
return sum[rt];
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
put_down(l, r, rt);
return ask(l, Mid, Lson, x, y) + ask(Mid + 1, r, Rson, x, y);
}
}a;
线段树(区间加,区间覆盖,区间和,区间最大值)
struct STree{
int sum[N * 4], la[N * 4], smax[N * 4], cola[N * 4], bj[N * 4];
void put_down(int l, int r, int rt){
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
if(bj[rt]){
sum[Lson] = cola[rt] * (Mid - l + 1);
smax[Lson] = cola[rt];
bj[Lson] = 1, cola[Lson] = cola[rt];
la[Lson] = 0;
sum[Rson] = cola[rt] * (r - Mid);
smax[Rson] = cola[rt];
bj[Rson] = 1, cola[Rson] = cola[rt];
la[Rson] = 0;
cola[rt] = 0;
bj[rt] = 0;
}
sum[Lson] += la[rt] * (Mid - l + 1);
smax[Lson] += la[rt];
la[Lson] += la[rt];
sum[Rson] += la[rt] * (r - Mid);
smax[Rson] += la[rt];
la[Rson] += la[rt];
la[rt] = 0;
}
void build(int l, int r, int rt){
bj[rt] = 0;
if(l == r){
scanf("%lld", &sum[rt]);
smax[rt] = sum[rt];
la[rt] = 0;
cola[rt] = 0;
return;
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
build(l, Mid, Lson), build(Mid + 1, r, Rson);
sum[rt] = sum[Lson] + sum[Rson];
smax[rt] = max(smax[Lson], smax[Rson]);
}
void add(int l, int r, int rt, int x, int y, int z){
if(l >= x && r <= y){
sum[rt] += z * (r - l + 1);
smax[rt] += z;
la[rt] += z;
return;
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
put_down(l, r, rt);
if(x <= Mid) add(l, Mid, Lson, x, y, z);
if(y > Mid) add(Mid + 1, r, Rson, x, y, z);
sum[rt] = sum[Lson] + sum[Rson];
smax[rt] = max(smax[Lson], smax[Rson]);
}
int ask(int l, int r, int rt, int x, int y){
if(l >= x && r <= y){
return sum[rt];
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
put_down(l, r, rt);
int ans = 0;
if(x <= Mid) ans += ask(l, Mid, Lson, x, y);
if(y > Mid) ans += ask(Mid + 1, r, Rson, x, y);
return ans;
}
int Max(int l, int r, int rt, int x, int y){
if(l >= x && r <= y){
return smax[rt];
}
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
put_down(l, r, rt);
int ans = -1e18;
if(x <= Mid) ans = max(ans, Max(l, Mid, Lson, x, y));
if(y > Mid) ans = max(ans, Max(Mid + 1, r, Rson, x, y));
return ans;
}
void cover(int l, int r, int rt, int x, int y, int z){
if(l >= x && r <= y){
sum[rt] = z * (r - l + 1);
cola[rt] = z;
smax[rt] = z;
bj[rt] = 1;
la[rt] = 0;
return;
}
put_down(l, r, rt);
int Lson = rt << 1, Rson = (rt << 1) + 1, Mid = (l + r) >> 1;
if(x <= Mid) cover(l, Mid, Lson, x, y, z);
if(y > Mid) cover(Mid + 1, r, Rson, x, y, z);
sum[rt] = sum[Lson] + sum[Rson];
smax[rt] = max(smax[Lson], smax[Rson]);
}
}a;
权值线段树
[普通平衡树](https://www.luogu.com.cn/problem/P3369
struct STree{
int sum[N * 30], Ls[N * 30], Rs[N * 30], cnt = 1;
void update(int l, int r, int rt){
sum[rt] = sum[Ls[rt]] + sum[Rs[rt]];
}
void add(int l, int r, int &rt, int x, int y){
if(!rt) rt = ++cnt;
if(l == r){
sum[rt] += y;
return;
}
int Mid = (l + r) >> 1;
if(x <= Mid) add(l, Mid, Ls[rt], x, y);
else add(Mid + 1, r, Rs[rt], x, y);
update(l, r, rt);
}
int ask(int l, int r, int rt, int x, int y){
if(x <= l && r <= y){
return sum[rt];
}
int ans = 0;
int Mid = (l + r) >> 1;
if(x <= Mid) ans += ask(l, Mid, Ls[rt], x, y);
if(y > Mid) ans += ask(Mid + 1, r, Rs[rt], x, y);
return ans;
}
int FoMax(int l, int r, int rt){
if(l == r) return l;
int Mid = (l + r) >> 1;
if(sum[Rs[rt]]) return FoMax(Mid + 1, r, Rs[rt]);
else return FoMax(l, Mid, Ls[rt]);
}
int FoMin(int l, int r, int rt){
if(l == r) return l;
int Mid = (l + r) >> 1;
if(sum[Ls[rt]]) return FoMin(l, Mid, Ls[rt]);
else return FoMin(Mid + 1, r, Rs[rt]);
}
int Max(int l, int r, int rt, int x){
int Mid = (l + r) >> 1;
if(r < x){
if(sum[rt]){
return FoMax(l, r, rt);
}
else{
return 0;
}
}
if(x > Mid + 1 && sum[Rs[rt]]){
int ans = Max(Mid + 1, r, Rs[rt], x);
if(ans) return ans;
}
return Max(l, Mid, Ls[rt], x);
}
int Min(int l, int r, int rt, int x){
int Mid = (l + r) >> 1;
if(l > x){
if(sum[rt]){
return FoMin(l, r, rt);
}
else{
return 0;
}
}
if(x <= Mid && sum[Ls[rt]]){
int ans = Min(l, Mid, Ls[rt], x);
if(ans) return ans;
}
return Min(Mid + 1, r, Rs[rt], x);
}
int kth(int l, int r, int rt, int x){
if(l == r){
return l;
}
int Mid = (l + r) >> 1;
if(x <= sum[Ls[rt]]){
return kth(l, Mid, Ls[rt], x);
}
else{
return kth(Mid + 1, r, Rs[rt], x - sum[Ls[rt]]);
}
}
}a;
线段树合并
struct STree{
int sum[M], Ls[M], Rs[M], cnt;
int mx[M], k[M];
void update(int l, int r, int rt){
sum[rt] = sum[Ls[rt]] + sum[Rs[rt]];
mx[rt] = max(mx[Ls[rt]], mx[Rs[rt]]);
k[rt] = mx[Ls[rt]] >= mx[Rs[rt]] ? k[Ls[rt]] : k[Rs[rt]];
}
void add(int l, int r, int &rt, int x, int y){
if(!rt) rt = ++cnt;
if(l == r){
sum[rt] += y;
mx[rt] += y;
k[rt] = l;
return;
}
int Mid = (l + r) >> 1;
if(x <= Mid) add(l, Mid, Ls[rt], x, y);
else add(Mid + 1, r, Rs[rt], x, y);
update(l, r, rt);
}
int ask(int l, int r, int rt, int x, int y){
if(x <= l && r <= y){
return sum[rt];
}
int ans = 0;
int Mid = (l + r) >> 1;
if(x <= Mid) ans += ask(l, Mid, Ls[rt], x, y);
if(y > Mid) ans += ask(Mid + 1, r, Rs[rt], x, y);
return ans;
}
int aks(int l, int r, int rt1, int rt2){
if(!rt1) return rt2;
if(!rt2) return rt1;
if(l == r){
sum[rt1] += sum[rt2];
mx[rt1] += mx[rt2];
if(mx[rt1]) k[rt1] = l;
else k[rt1] = 0;
return rt1;
}
int Mid = (l + r) >> 1;
Ls[rt1] = aks(l, Mid, Ls[rt1], Ls[rt2]);
Rs[rt1] = aks(Mid + 1, r, Rs[rt1], Rs[rt2]);
update(l, r, rt1);
return rt1;
}
int Max(int l, int r, int rt){
return k[rt];
}
}a;
可持久化线段树(静态区间第k小)
struct STree{
int sum[N * 32], L[N * 32], R[N * 32], cnt;
void update(int rt){
sum[rt] = sum[L[rt]] + sum[R[rt]];
}
void build(int &rt, int l, int r, int x){
if(!rt) rt = ++cnt;
if(l == r){
sum[rt]++;
return;
}
int mid = (l + r) >> 1;
if(x <= mid) build(L[rt], l, mid, x);
if(x > mid) build(R[rt], mid + 1, r, x);
update(rt);
}
void add(int p, int &q, int l, int r, int x){
if(!q) q = ++cnt;
if(l == r){
sum[q] = sum[p] + 1;
return;
}
int mid = (l + r) >> 1;
if(x <= mid){
R[q] = R[p];
add(L[p], L[q], l, mid, x);
}
if(x > mid){
L[q] = L[p];
add(R[p], R[q], mid + 1, r, x);
}
update(q);
}
int ask(int p, int q, int l, int r, int x){
if(l == r) return l;
int mid = (l + r) >> 1;
int cntl = sum[L[q]] - sum[L[p]];
if(cntl >= x){
return ask(L[p], L[q], l, mid, x);
}
else{
return ask(R[p], R[q], mid + 1, r, x - cntl);
}
}
}S;
可持久化线段树(动态区间第k小)
struct STree{
int sum[N * 441], L[N * 441], R[N * 441], cnt;
int ask(int l, int r, int k){
if(l == r) return l;
int cntk = 0;
for(int i = 1; i <= cntx; i++)
cntk -= sum[L[cx[i]]];
for(int i = 1; i <= cnty; i++)
cntk += sum[L[cy[i]]];
int mid = (l + r) >> 1;
if(cntk >= k){
for(int i = 1; i <= cntx; i++)
cx[i] = L[cx[i]];
for(int i = 1; i <= cnty; i++)
cy[i] = L[cy[i]];
return ask(l, mid, k);
}
else{
for(int i = 1; i <= cntx; i++)
cx[i] = R[cx[i]];
for(int i = 1; i <= cnty; i++)
cy[i] = R[cy[i]];
return ask(mid + 1, r, k - cntk);
}
}
void add(int &rt, int l, int r, int x, int y){
if(!rt) rt = ++cnt;
sum[rt] += y;
if(l == r){
return;
}
int mid = (l + r) >> 1;
if(x <= mid){
add(L[rt], l, mid, x, y);
}
else{
add(R[rt], mid + 1, r, x, y);
}
}
}S;