板子汇总
可持久化线段树
struct Persistent_Segment_Tree
{
struct Point
{
int l, r;
LL sum;
}p[N * 25];
int rt[N], cnt = 0;
void Newpoint(int &rt, int last, int l, int r, int x, int v)
{
rt = ++cnt;
p[rt] = p[last], p[rt].sum += v;
if (l == r) return;
int mid = l + r >> 1;
if (x <= mid) Newpoint(p[rt].l, p[last].l, l, mid, x, v);
else Newpoint(p[rt].r, p[last].r, mid + 1, r, x, v);
}
LL Query(int rt_1, int rt_2, int l, int r, int x, int y)
{
if(x <= l && y >= r)
return p[rt_2].sum - p[rt_1].sum;
LL res = 0;
int mid = l + r >> 1;
if (x <= mid)
res += Query(p[rt_1].l, p[rt_2].l, l, mid, x, y);
if (y >= mid + 1)
res += Query(p[rt_1].r, p[rt_2].r, mid + 1, r, x, y);
return res;
}
}PT;
多源最短路(Johnson算法)
struct Johnson
{
int n, m, d[N], dis[N], vis[N], Dis[N][N];
priority_queue <pair<int, int> > q;
bool Bellman_Ford()
{
for (int i = 1; i <= n; i++) g[0].push_back(MP(i, 0)), d[i] = INF;
int flag = 0;
for (int i = 1; i <= n; i++)
{
int Flag = 0;
for (int j = 0; j <= n; j++)
for (int k = 0; k < g[j].size(); k++)
{
int v = g[j][k].F, w = g[j][k].S;
if (w + d[j] < d[v])
Flag = 1, d[v] = d[j] + w;
}
if (!Flag)
{
flag = 1;
break;
}
}
return flag;
}
void Dijkstra(int S)
{
for (int i = 1; i <= n; i++) dis[i] = INF, vis[i] = 0;
dis[S] = 0, q.push(MP(0, S));
while (!q.empty())
{
int x = q.top().S;
q.pop();
if (vis[x]) continue;
vis[x] = 1;
for (int i = 0; i < g[x].size(); i++)
{
int v = g[x][i].F, w = g[x][i].S + d[x] - d[v];
if (dis[v] > dis[x] + w) dis[v] = dis[x] + w, q.push(MP(-dis[v], v));
}
}
for (int i = 1; i <= n; i++)
Dis[S][i] = dis[i];
}
void work()
{
if (!Bellman_Ford()) puts("exist minus circle");
else for (int i = 1; i <= n; i++) Dijkstra(i);
}
}J;
线段树
- 区间加+区间乘+区间求和
struct Segment_Tree
{
LL tag_a[N * 4], tag_m[N * 4], sum[N * 4], a[N], m;
void init(int n)
{
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
}
int lc(int k) { return k << 1; }
int rc(int k) { return k << 1 | 1; }
void push_up(int k)
{
sum[k] = (sum[lc(k)] + sum[rc(k)]) % m;
}
void push_down(int k, int l, int r)
{
int mid = l + r >> 1;
sum[lc(k)] = (sum[lc(k)] * tag_m[k] % m + tag_a[k] * (mid - l + 1) % m) % m;
tag_m[lc(k)] = tag_m[lc(k)] * tag_m[k] % m;
tag_a[lc(k)] = (tag_a[lc(k)] * tag_m[k] % m + tag_a[k]) % m;
sum[rc(k)] = (sum[rc(k)] * tag_m[k] % m + tag_a[k] * (r - mid) % m) % m;
tag_m[rc(k)] = tag_m[rc(k)] * tag_m[k] % m;
tag_a[rc(k)] = (tag_a[rc(k)] * tag_m[k] % m + tag_a[k]) % m;
tag_a[k] = 0, tag_m[k] = 1;
}
void build(int k, int l, int r)
{
tag_m[k] = 1;
if (l == r) { sum[k] = a[l] % m; return; }
int mid = l + r >> 1;
build(lc(k), l, mid);
build(rc(k), mid + 1, r);
push_up(k);
}
void modify_a(int k, int l, int r, int x, int y, LL v)
{
if (x <= l && r <= y)
{
sum[k] = (sum[k] + (r - l + 1) * v) % m;
tag_a[k] = (tag_a[k] + v) % m;
return;
}
push_down(k, l, r);
int mid = l + r >> 1;
if (x <= mid) modify_a(lc(k), l, mid, x, y, v);
if (y >= mid + 1) modify_a(rc(k), mid + 1, r, x, y, v);
push_up(k);
}
void modify_m(int k, int l, int r, int x, int y, LL v)
{
if (x <= l && r <= y)
{
sum[k] = sum[k] * v % m;
tag_m[k] = (tag_m[k] * v) % m;
tag_a[k] = (tag_a[k] * v) % m;
return;
}
push_down(k, l, r);
int mid = l + r >> 1;
if (x <= mid) modify_m(lc(k), l, mid, x, y, v);
if (y >= mid + 1) modify_m(rc(k), mid + 1, r, x, y, v);
push_up(k);
}
LL query(int k, int l, int r, int x, int y)
{
if (x <= l && r <= y)
return sum[k];
push_down(k, l, r);
int mid = l + r >> 1;
LL res = 0;
if (x <= mid) res += query(lc(k), l, mid, x, y);
if (y >= mid + 1) res += query(rc(k), mid + 1, r, x, y);
return res % m;
}
}ST;
- 区间加+区间求和+区间求最值
struct Segment_Tree
{
LL tag_a[N * 4], sum[N * 4], a[N], Max[N * 4], Min[N * 4];
void init(int n)
{
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
}
int lc(int k) { return k << 1; }
int rc(int k) { return k << 1 | 1; }
void push_up(int k)
{
sum[k] = sum[lc(k)] + sum[rc(k)];
Max[k] = max(Max[lc(k)], Max[rc(k)]);
Min[k] = min(Min[lc(k)], Min[rc(k)]);
}
void push_down(int k, int l, int r)
{
int mid = l + r >> 1;
sum[lc(k)] = sum[lc(k)] + tag_a[k] * (mid - l + 1);
Max[lc(k)] = Max[lc(k)] + tag_a[k];
Min[lc(k)] = Min[lc(k)] + tag_a[k];
tag_a[lc(k)] = tag_a[lc(k)] + tag_a[k];
sum[rc(k)] = sum[rc(k)] + tag_a[k] * (r - mid);
Max[rc(k)] = Max[rc(k)] + tag_a[k];
Min[rc(k)] = Min[rc(k)] + tag_a[k];
tag_a[rc(k)] = tag_a[rc(k)] + tag_a[k];
tag_a[k] = 0;
}
void build(int k, int l, int r)
{
if (l == r) { Min[k] = Max[k] = sum[k] = a[l]; return; }
int mid = l + r >> 1;
build(lc(k), l, mid);
build(rc(k), mid + 1, r);
push_up(k);
}
void modify_a(int k, int l, int r, int x, int y, LL v)
{
if (x <= l && r <= y)
{
sum[k] = sum[k] + (r - l + 1) * v;
tag_a[k] = tag_a[k] + v;
Max[k] = Max[k] + v;
Min[k] = Min[k] + v;
return;
}
push_down(k, l, r);
int mid = l + r >> 1;
if (x <= mid) modify_a(lc(k), l, mid, x, y, v);
if (y >= mid + 1) modify_a(rc(k), mid + 1, r, x, y, v);
push_up(k);
}
LL query_sum(int k, int l, int r, int x, int y)
{
if (x <= l && r <= y)
return sum[k];
push_down(k, l, r);
int mid = l + r >> 1;
LL res = 0;
if (x <= mid) res += query_sum(lc(k), l, mid, x, y);
if (y >= mid + 1) res += query_sum(rc(k), mid + 1, r, x, y);
return res;
}
LL query_Max(int k, int l, int r, int x, int y)
{
if (x <= l && r <= y)
return Max[k];
push_down(k, l, r);
int mid = l + r >> 1;
LL res = 0;
if (x <= mid) res = max(res, query_Max(lc(k), l, mid, x, y));
if (y >= mid + 1) res = max(res, query_Max(rc(k), mid + 1, r, x, y));
return res;
}
LL query_Min(int k, int l, int r, int x, int y)
{
if (x <= l && r <= y)
return Min[k];
push_down(k, l, r);
int mid = l + r >> 1;
LL res = INF;
if (x <= mid) res = min(res, query_Max(lc(k), l, mid, x, y));
if (y >= mid + 1) res = min(res, query_Max(rc(k), mid + 1, r, x, y));
return res;
}
}ST;
树状数组
struct Binary_Index_Tree
{
LL c[N];
int n;
int lowbit(int x)
{
return x & (-x);
}
void add(int x, int v)
{
for (int i = x; i <= n; i += lowbit(i)) c[i] += v;
}
LL query_sum(int x)
{
LL res = 0;
while (x) res += c[x], x -= lowbit(x);
return res;
}
}BIT;
树链剖分
struct Segment_Tree
{
LL tag[N * 4], sum[N * 4], a[N];
int lc(int k) { return k << 1; }
int rc(int k) { return k << 1 | 1; }
void push_up(int k)
{
sum[k] = (sum[lc(k)] + sum[rc(k)]) % p;
}
void push_down(int k, int l, int r)
{
int mid = l + r >> 1;
sum[lc(k)] = (sum[lc(k)] + tag[k] * (mid - l + 1) % p) % p;
tag[lc(k)] = (tag[lc(k)] + tag[k]) % p;
sum[rc(k)] = (sum[rc(k)] + tag[k] * (r - mid) % p) % p;
tag[rc(k)] = (tag[rc(k)] + tag[k]) % p;
tag[k] = 0;
}
void build(int k, int l, int r)
{
if (l == r) { sum[k] = a[l] % p; return; }
int mid = l + r >> 1;
build(lc(k), l, mid);
build(rc(k), mid + 1, r);
push_up(k);
}
void modify(int k, int l, int r, int x, int y, LL v)
{
if (x <= l && r <= y)
{
sum[k] = (sum[k] + v * (r - l + 1) % p) % p;
tag[k] = (tag[k] + v) % p;
return;
}
push_down(k, l, r);
int mid = l + r >> 1;
if (x <= mid) modify(lc(k), l, mid, x, y, v);
if (y >= mid + 1) modify(rc(k), mid + 1, r, x, y, v);
push_up(k);
}
LL query(int k, int l, int r, int x, int y)
{
if (x <= l && r <= y)
return sum[k];
push_down(k, l, r);
int mid = l + r >> 1;
LL res = 0;
if (x <= mid) res += query(lc(k), l, mid, x, y);
if (y >= mid + 1) res += query(rc(k), mid + 1, r, x, y);
return res % p;
}
}ST;
struct Heavy_Light_Path_Divide
{
int son[N], siz[N], top[N], dfn[N], idfn[N], dep[N], f[N], Index, a[N];
void dfs_1(int x, int fa)
{
siz[x] = 1;
for (int i = 0; i < g[x].size(); i++)
{
int v = g[x][i];
if (v == fa) continue;
dep[v] = dep[x] + 1, f[v] = x;
dfs_1(v, x);
siz[x] += siz[v];
if (siz[son[x]] < siz[v])
son[x] = v;
}
}
void dfs_2(int x, int fa, int t)
{
dfn[x] = ++Index, idfn[Index] = x, top[x] = t;
if (son[x])
dfs_2(son[x], x, t);
for (int i = 0; i < g[x].size(); i++)
{
int v = g[x][i];
if (v == fa || v == son[x])
continue;
dfs_2(v, x, v);
}
}
void modify_path(int x, int y, int v)
{
int tx = top[x], ty = top[y];
while (tx != ty)
{
if (dep[tx] > dep[ty])
{
ST.modify(1, 1, n, dfn[tx], dfn[x], v);
x = f[tx], tx = top[x];
}
else
{
ST.modify(1, 1, n, dfn[ty], dfn[y], v);
y = f[ty], ty = top[y];
}
}
if (dfn[x] < dfn[y])
ST.modify(1, 1, n, dfn[x], dfn[y], v);
else
ST.modify(1, 1, n, dfn[y], dfn[x], v);
}
void modify_sub(int x, LL v)
{
ST.modify(1, 1, n, dfn[x], dfn[x] + siz[x] - 1, v);
}
LL query_sub(int x)
{
return ST.query(1, 1, n, dfn[x], dfn[x] + siz[x] - 1);
}
LL query_path(int x, int y)
{
LL res = 0;
int tx = top[x], ty = top[y];
while (tx != ty)
{
if (dep[tx] > dep[ty])
{
res = (res + ST.query(1, 1, n, dfn[tx], dfn[x])) % p;
x = f[tx], tx = top[x];
}
else
{
res = (res + ST.query(1, 1, n, dfn[ty], dfn[y])) % p;
y = f[ty], ty = top[y];
}
}
if (dfn[x] < dfn[y])
res = (res + ST.query(1, 1, n, dfn[x], dfn[y])) % p;
else
res = (res + ST.query(1, 1, n, dfn[y], dfn[x])) % p;
return res;
}
void work()
{
dfs_1(1, -1);
dfs_2(1, -1, 1);
for (int i = 1; i <= n; i++) ST.a[i] = a[idfn[i]];
ST.build(1, 1, n);
}
}PD;
Tarjan系列算法
强连通分量(缩点)
struct SCC
{
int Index, dfn[N], low[N], cnt, S[N], top, Iscc[N], ins[N];
vector<int> scc[N];
void Tarjan(int x)
{
low[x] = dfn[x] = ++Index;
ins[x] = 1, S[++top] = x;
for (int i = 0; i < g[x].size(); i++)
{
int v = g[x][i];
if (!dfn[v])
Tarjan(v), low[x] = min(low[x], low[v]);
else if (ins[v])
low[x] = min(low[x], dfn[v]);
}
if (dfn[x] == low[x])
{
cnt++; int y;
do
{
y = S[top--], ins[y] = 0;
scc[cnt].push_back(y), Iscc[y] = cnt, A[cnt] += a[y];
} while (x != y);
}
}
void work()
{
for (int i = 1; i <= n; i++)
if (!dfn[i]) Tarjan(i);
for (int i = 1; i <= n; i++)
for (int j = 0; j < g[i].size(); j++)
{
int v = g[i][j];
if (Iscc[i] != Iscc[v])
ng[Iscc[i]].push_back(Iscc[v]);
}
}
}SC;
欧拉路
记得跑之前把以每个点为起始点的边按终点排序
void Euler_road(int from)
{
S[++top] = from;
while (top)
{
int x = S[top];
while (Now[x] < (int)g[x].size() && vis[x][g[x][Now[x]]] == 1)
Now[x]++;
if (Now[x] < (int)g[x].size())
{
int v = g[x][Now[x]];
S[++top] = v, vis[x][v] = vis[v][x] = 1, Now[x]++;
}
else
ans[++ans[0]] = S[top--];
}
}
由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!