st表
int query(int l, int r) {
int k = __lg(r - l + 1);
return __gcd(st[l][k], st[r - (1 << k) + 1][k]);
}
void solve() {
// 此处维护区间gcd
for(int i = 1; i <= n; i++) {
st[i][0] = abs(a[i + 1] - a[i]);
}
for(int k = 1; k <= __lg(n); k++) {
for(int i = 1; i + (1 << k) - 1 <= n; i++) {
st[i][k] = __gcd(st[i][k - 1], st[i + (1 << k - 1)][k - 1]);
}
}
}
树状数组
// 此题开了21个树状数组,非常恶心
int tr[22][K + 10];
int lowbit(int x) {
return x & -x;
}
void update(int i, int x, int d) {
x++;
while(x <= K) {
tr[i][x] += d;
x += lowbit(x);
}
}
int qu(int i, int x) {
x++;
int ans = 0;
while(x) {
ans += tr[i][x];
x -= lowbit(x);
}
return ans;
}
int query(int i, int l, int r) {
return qu(i, r) - qu(i, l - 1);
}
动态开点线段树
void update(int i, ll l, ll r, ll q, int x) {
num[i] = x;
if(l == r) return;
ll mid = (l + r) / 2;
if(q <= mid) {
if(!ls[i]) ls[i] = ++cnt;
update(ls[i], l, mid, q, x);
} else {
if(!rs[i]) rs[i] = ++cnt;
update(rs[i], mid + 1, r, q, x);
}
}
树链剖分
ll w0[N];
int dep[N], f[N], sz[N], son[N];
void dfs1(int l, int i) {
f[i] = l;
dep[i] = dep[l] + 1;
int ms = -1;
for(int j = 0; j < v[i].size(); j++) {
int t = v[i][j];
if(t == l) continue;
dfs1(i, t);
sz[i] += sz[t] + 1;
if(sz[t] > ms) {
ms = sz[t];
son[i] = t;
}
}
}
int id[N], z, up[N];
ll w[N];
void dfs2(int i, int iup) {
z++;
id[i] = z;
w[z] = w0[i];
up[i] = iup;
if(son[i] == 0) return;
dfs2(son[i], iup);
for(int j = 0; j < v[i].size(); j++) {
int t = v[i][j];
if(t == f[i] || t == son[i]) continue;
dfs2(t, t);
}
}
ll sum[N * 4], lz[N * 4];
void pushup(int i) {
sum[i] = sum[i * 2] + sum[i * 2 + 1];
sum[i] %= mo;
}
void build(int i, int l, int r) {
if(l == r) {
sum[i] = w[l];
return;
}
int mid = (l + r) / 2;
build(i * 2, l, mid);
build(i * 2 + 1, mid + 1, r);
pushup(i);
}
void pushdown(int i, int l, int r) {
if(lz[i]) {
int mid = (l + r) / 2;
sum[i * 2] += (mid - l + 1) * lz[i];
sum[i * 2] %= mo;
sum[i * 2 + 1] += (r - mid) * lz[i];
sum[i * 2 + 1] %= mo;
lz[i * 2] += lz[i];
lz[i * 2] %= mo;
lz[i * 2 + 1] += lz[i];
lz[i * 2 + 1] %= mo;
lz[i] = 0;
}
}
void modify(int i, int l, int r, int ql, int qr, ll d) {
if(ql <= l && qr >= r) {
sum[i] += (r - l + 1) * d;
sum[i] %= mo;
lz[i] += d;
lz[i] %= mo;
return;
}
pushdown(i, l, r);
int mid = (l + r) / 2;
if(ql <= mid) modify(i * 2, l, mid, ql, qr, d);
if(qr > mid) modify(i * 2 + 1, mid + 1, r, ql, qr, d);
pushup(i);
}
ll query(int i, int l, int r, int ql, int qr) {
if(ql <= l && qr >= r) return sum[i];
pushdown(i, l, r);
int mid = (l + r) / 2;
ll ans = 0;
if(ql <= mid) ans += query(i * 2, l, mid, ql, qr);
if(qr > mid) ans += query(i * 2 + 1, mid + 1, r, ql, qr);
ans %= mo;
pushup(i);
return ans;
}
void op1(int x, int y, ll d) {
while(up[x] != up[y]) {
if(dep[up[x]] < dep[up[y]]) swap(x, y);
modify(1, 1, n, id[up[x]], id[x], d);
x = f[up[x]];
}
if(dep[x] > dep[y]) swap(x, y);
modify(1, 1, n, id[x], id[y], d);
}
ll op2(int x, int y) {
ll ans = 0;
while(up[x] != up[y]) {
if(dep[up[x]] < dep[up[y]]) swap(x, y);
ans += query(1, 1, n, id[up[x]], id[x]);
ans %= mo;
x = f[up[x]];
}
if(dep[x] > dep[y]) swap(x, y);
ans += query(1, 1, n, id[x], id[y]);
ans %= mo;
return ans;
}