可并堆
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
#define mp make_pair
#define db double
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
void Min(int& x, int y) {
x = (x < y) ? x : y;
}
void Max(int& x, int y) {
x = (x > y) ? x : y;
}
int add(int x, int y) {
return (x + y) >= mod ? (x + y - mod) : (x + y);
}
int sub(int x, int y) {
return (x < y) ? (x + mod - y) : (x - y);
}
void Add(int& x, int y) {
x = (x + y) >= mod ? (x + y - mod) : (x + y);
}
void Sub(int& x, int y) {
x = (x < y) ? (x - y + mod) : (x - y);
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
void Mul(int& x, int y) {
x = 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
int ans = 1;
while (y) {
if (y & 1)
ans = 1ll * x * ans % mod;
x = 1ll * x * x % mod, y >>= 1;
}
return ans;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, m;
int rt[maxn], dis[maxn], ls[maxn], rs[maxn], vis[maxn];
pii val[maxn];
int find(int x) {
if (x == rt[x])
return x;
return (rt[x] = find(rt[x]));
}
int merge(int x, int y) {
if (!x || !y)
return (x | y);
if (val[x] > val[y])
swap(x, y);
rs[x] = merge(rs[x], y);
if (dis[ls[x]] < dis[rs[x]])
swap(ls[x], rs[x]);
dis[x] = dis[rs[x]] + 1;
return x;
}
signed main() {
openfile();
n = read(), m = read();
for (int i = 1; i <= n; i++)
rt[i] = i, val[i].first = read(), val[i].second = i;
while (m--) {
int op = read(), x, y;
if (op == 1) {
x = read(), y = read();
if (vis[x] || vis[y])
continue;
x = find(x), y = find(y);
if (x != y)
rt[x] = rt[y] = merge(x, y);
}
else {
x = read();
if (vis[x]) {
puts("-1");
continue;
}
x = find(x);
printf("%d\n", val[x].first), vis[x] = 1;
rt[ls[x]] = rt[rs[x]] = rt[x] = merge(ls[x], rs[x]);
ls[x] = rs[x] = dis[x] = 0;
}
}
return 0;
}
可持久化并查集
#include <bits/stdc++.h>
#define N 300005
using namespace std;
int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
int n, m, now, to, cnt, rt[N];
struct tree {
int ls, rs, fa, dep;
} tr[N * 20];
inline int build(int l, int r) {
int to = ++cnt;
if (l == r) {
tr[to].fa = l;
return to;
}
int mid = (l + r) >> 1;
tr[to].ls = build(l, mid);
tr[to].rs = build(mid + 1, r);
return to;
}
inline int que(int now, int l, int r, int x) {
if (l == r)
return now;
int mid = (l + r) >> 1;
if (mid >= x)
return que(tr[now].ls, l, mid, x);
else
return que(tr[now].rs, mid + 1, r, x);
}
inline int find(int now, int a) {
int fa = que(rt[now], 1, n, a);
if (tr[fa].fa == a)
return fa;
return find(now, tr[fa].fa);
}
inline int news(int now) {
int to = ++cnt;
tr[to] = tr[now];
return to;
}
inline int hb(int now, int l, int r, int x, int f) {
int to = news(now);
if (l == r) {
tr[to].fa = f;
return to;
}
int mid = (l + r) >> 1;
if (mid >= x)
tr[to].ls = hb(tr[now].ls, l, mid, x, f);
else
tr[to].rs = hb(tr[now].rs, mid + 1, r, x, f);
return to;
}
inline int add(int now, int l, int r, int x) {
int to = news(now);
if (l == r) {
tr[to].dep++;
return to;
}
int mid = (l + r) >> 1;
if (mid >= x)
tr[to].ls = add(tr[now].ls, l, mid, x);
else
tr[to].rs = add(tr[now].rs, mid + 1, r, x);
return to;
}
inline void merge(int now, int a, int b) {
rt[now] = rt[now - 1];
a = find(now, a);
b = find(now, b);
if (tr[a].fa != tr[b].fa) {
if (tr[a].dep > tr[b].dep)
swap(a, b);
rt[now] = hb(rt[now - 1], 1, n, tr[a].fa, tr[b].fa);
if (tr[a].dep == tr[b].dep)
rt[now] = add(rt[now], 1, n, tr[b].fa);
}
}
inline bool pan(int now, int a, int b) {
a = find(now, a), b = find(now, b);
if (tr[a].fa == tr[b].fa)
return 1;
else
return 0;
}
int main() {
n = read();
m = read();
rt[0] = build(1, n);
int op, a, b;
for (int i = 1; i <= m; i++) {
op = read();
a = read();
if (op == 1) {
b = read();
merge(i, a, b);
}
if (op == 2)
rt[i] = rt[a];
if (op == 3) {
b = read();
if (pan(i - 1, a, b))
cout << 1 << "\n";
else
cout << 0 << "\n";
rt[i] = rt[i - 1];
}
}
return 0;
}
快速RMQ和LCA
树状数组
#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
const int maxn = 1e6 + 10;
template <typename T> inline void read(T& x) {
x = 0;
char c = getchar();
bool f = 0;
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return;
}
int n, m;
int a[maxn];
int t[maxn];
void add(int x, int val) {
for (; x <= n; x += lowbit(x)) {
t[x] += val;
}
}
int ask(int x) {
int ans = 0;
for (; x; x -= lowbit(x))
ans += t[x];
return ans;
}
int sum(int x, int y) {
return ask(y) - ask(x - 1);
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
read(n), read(m);
for (int i = 1; i <= n; i++)
read(a[i]), add(i, a[i]);
for (int i = 1; i <= m; i++) {
int op, x, y;
read(op), read(x), read(y);
if (op == 1)
add(x, y);
if (op == 2)
printf("%d\n", sum(x, y));
}
return 0;
}
线段树2
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e5 + 10;
int n, m, mod;
int a[maxn];
struct tree
{
int l, r, val, mul, add;
} t[maxn * 4];
void build(int tr, int l, int r)
{
t[tr].l = l, t[tr].r = r, t[tr].mul = 1;
if (l == r)
{
t[tr].val = a[l];
return;
}
int mid = l + r >> 1;
build(tr << 1, l, mid);
build(tr << 1 | 1, mid + 1, r);
t[tr].val = t[tr << 1].val + t[tr << 1 | 1].val;
t[tr].val %= mod;
return;
}
void pushdown(int x)
{
t[x << 1].val = t[x << 1].val * t[x].mul + t[x].add * (t[x << 1].r - t[x << 1].l + 1);
t[x << 1].val %= mod;
t[x << 1 | 1].val = t[x << 1 | 1].val * t[x].mul + t[x].add * (t[x << 1 | 1].r - t[x << 1 | 1].l + 1);
t[x << 1 | 1].val %= mod;
(t[x << 1].mul *= t[x].mul) %= mod;
(t[x << 1 | 1].mul *= t[x].mul) %= mod;
t[x << 1].add = (t[x << 1].add * t[x].mul + t[x].add) % mod;
t[x << 1 | 1].add = (t[x << 1 | 1].add * t[x].mul + t[x].add) % mod;
t[x].mul = 1, t[x].add = 0;
return;
}
void mul(int tr, int l, int r, int val)
{
if (t[tr].l >= l && t[tr].r <= r)
{
(t[tr].val *= val) %= mod;
(t[tr].mul *= val) %= mod;
(t[tr].add *= val) %= mod;
return;
}
pushdown(tr);
int mid = t[tr].l + t[tr].r >> 1;
if (l <= mid)
mul(tr << 1, l, r, val);
if (r > mid)
mul(tr << 1 | 1, l, r, val);
t[tr].val = t[tr << 1].val + t[tr << 1 | 1].val;
t[tr].val %= mod;
return;
}
void add(int tr, int l, int r, int val)
{
if (t[tr].l >= l && t[tr].r <= r)
{
(t[tr].val += val * (t[tr].r - t[tr].l + 1)) %= mod;
(t[tr].add += val) %= mod;
return;
}
pushdown(tr);
int mid = t[tr].l + t[tr].r >> 1;
if (l <= mid)
add(tr << 1, l, r, val);
if (r > mid)
add(tr << 1 | 1, l, r, val);
t[tr].val = t[tr << 1].val + t[tr << 1 | 1].val;
t[tr].val %= mod;
return;
}
int ask(int tr, int l, int r)
{
int ans = 0;
if (t[tr].l >= l && t[tr].r <= r)
return t[tr].val;
pushdown(tr);
int mid = t[tr].l + t[tr].r >> 1;
if (l <= mid)
ans += ask(tr << 1, l, r);
if (r > mid)
ans += ask(tr << 1 | 1, l, r);
ans %= mod;
return ans;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin >> n >> m >> mod;
for (int i = 1; i <= n; i++)
cin >> a[i];
build(1, 1, n);
while (m--)
{
int op;
cin >> op;
if (op == 1)
{
int x, y, k;
cin >> x >> y >> k;
mul(1, x, y, k);
}
if (op == 2)
{
int x, y, k;
cin >> x >> y >> k;
add(1, x, y, k);
}
if (op == 3)
{
int x, y;
cin >> x >> y;
cout << ask(1, x, y) << endl;
}
}
return 0;
}
线段树3
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ls (rt << 1)
#define rs (ls | 1)
const int maxn = 5e5 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
int add(int x, int y) {
x += y;
if (x >= mod)
x -= mod;
return x;
}
int sub(int x, int y) {
x -= y;
if (x < 0)
x += mod;
return x;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, q, a[maxn];
struct node {
int mx, hmx, se, cnt;
int sum;
int ad1, add1, ad2, add2;
int l, r;
} t[maxn << 2];
// mx是最大值,hmx是历史最大值,se是次大值,cnt是最大值有多少个,sum是区间和,ad1是最大值的加法标记,add1是最大值历史最大加法标记,ad2是其他的加法标记,add2是其他的历史最大加法标记
int max(int x, int y) {
return x > y ? x : y;
}
int min(int x, int y) {
return x < y ? x : y;
}
void pushup(int rt) {
t[rt].sum = t[ls].sum + t[rs].sum;
t[rt].hmx = max(t[ls].hmx, t[rs].hmx);
if (t[ls].mx == t[rs].mx) {
t[rt].mx = t[ls].mx;
t[rt].cnt = t[ls].cnt + t[rs].cnt;
t[rt].se = max(t[ls].se, t[rs].se);
}
if (t[ls].mx < t[rs].mx) {
t[rt].mx = t[rs].mx;
t[rt].cnt = t[rs].cnt;
t[rt].se = max(t[ls].mx, t[rs].se);
}
if (t[rs].mx < t[ls].mx) {
t[rt].mx = t[ls].mx;
t[rt].cnt = t[ls].cnt;
t[rt].se = max(t[ls].se, t[rs].mx);
}
}
void build(int rt, int l, int r) {
t[rt].l = l, t[rt].r = r;
if (l == r) {
t[rt].sum = t[rt].hmx = t[rt].mx = a[l];
t[rt].se = -inf, t[rt].cnt = 1;
return;
}
int mid = (l + r) >> 1;
build(ls, l, mid), build(rs, mid + 1, r);
pushup(rt);
}
void add(int rt, int k1, int kk1, int k2, int kk2) {
t[rt].sum += t[rt].cnt * k1 + (t[rt].r - t[rt].l + 1 - t[rt].cnt) * k2;
t[rt].hmx = max(t[rt].hmx, t[rt].mx + kk1);
t[rt].mx += k1;
t[rt].add1 = max(t[rt].add1, t[rt].ad1 + kk1);
t[rt].ad1 += k1;
t[rt].add2 = max(t[rt].add2, t[rt].ad2 + kk2);
t[rt].ad2 += k2;
if (t[rt].se != -inf)
t[rt].se += k2;
}
void pushdown(int rt) {
int tmp = max(t[ls].mx, t[rs].mx);
if (t[ls].mx == tmp)
add(ls, t[rt].ad1, t[rt].add1, t[rt].ad2, t[rt].add2);
else
add(ls, t[rt].ad2, t[rt].add2, t[rt].ad2, t[rt].add2);
if (t[rs].mx == tmp)
add(rs, t[rt].ad1, t[rt].add1, t[rt].ad2, t[rt].add2);
else
add(rs, t[rt].ad2, t[rt].add2, t[rt].ad2, t[rt].add2);
t[rt].ad1 = t[rt].add1 = t[rt].ad2 = t[rt].add2 = 0;
}
void change1(int rt, int l, int r, int x, int y, int v) {
if (x <= l && r <= y) {
add(rt, v, v, v, v);
return;
}
int mid = (l + r) >> 1;
pushdown(rt);
if (x <= mid)
change1(ls, l, mid, x, y, v);
if (y > mid)
change1(rs, mid + 1, r, x, y, v);
pushup(rt);
}
void change2(int rt, int l, int r, int x, int y, int v) {
if (v >= t[rt].mx)
return;
if (x <= l && r <= y && v > t[rt].se) {
add(rt, v - t[rt].mx, v - t[rt].mx, 0, 0);
return;
}
int mid = (l + r) >> 1;
pushdown(rt);
if (x <= mid)
change2(ls, l, mid, x, y, v);
if (y > mid)
change2(rs, mid + 1, r, x, y, v);
pushup(rt);
}
int querysum(int rt, int l, int r, int x, int y) {
if (x <= l && r <= y)
return t[rt].sum;
pushdown(rt);
int mid = (l + r) >> 1;
int ans = 0;
if (x <= mid)
ans += querysum(ls, l, mid, x, y);
if (y > mid)
ans += querysum(rs, mid + 1, r, x, y);
return ans;
}
int querymax(int rt, int l, int r, int x, int y) {
if (x <= l && r <= y)
return t[rt].mx;
int ans = -inf, mid = (l + r) >> 1;
pushdown(rt);
if (x <= mid)
ans = max(ans, querymax(ls, l, mid, x, y));
if (y > mid)
ans = max(ans, querymax(rs, mid + 1, r, x, y));
return ans;
}
int queryhmax(int rt, int l, int r, int x, int y) {
if (x <= l && r <= y)
return t[rt].hmx;
pushdown(rt);
int ans = -inf, mid = (l + r) >> 1;
if (x <= mid)
ans = max(ans, queryhmax(ls, l, mid, x, y));
if (y > mid)
ans = max(ans, queryhmax(rs, mid + 1, r, x, y));
return ans;
}
signed main() {
openfile();
n = read(), q = read();
for (int i = 1; i <= n; i++)
a[i] = read();
build(1, 1, n);
while (q--) {
int op = read(), l, r, x;
switch (op) {
case 1:
l = read(), r = read(), x = read();
change1(1, 1, n, l, r, x);
break;
case 2:
l = read(), r = read(), x = read();
change2(1, 1, n, l, r, x);
break;
case 3:
l = read(), r = read();
printf("%lld\n", querysum(1, 1, n, l, r));
break;
case 4:
l = read(), r = read();
printf("%lld\n", querymax(1, 1, n, l, r));
break;
case 5:
l = read(), r = read();
printf("%lld\n", queryhmax(1, 1, n, l, r));
break;
}
}
cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
return 0;
}
线段树合并
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int son[maxn], dfn[maxn], dep[maxn], f[maxn], siz[maxn], top[maxn];
int n, m, cnt, ans[maxn], rt[maxn], tim;
int head[maxn], tot;
struct node {
int y, nex;
} e[maxn << 1];
struct tree {
int val, ans, l, r;
} t[maxn << 5];
void add(int x, int y) {
e[++tot] = {y, head[x]};
head[x] = tot;
}
void dfs1(int x, int fa) {
dep[x] = dep[fa] + 1;
siz[x] = 1;
f[x] = fa;
int maxx = 0;
for (int i = head[x]; i; i = e[i].nex) {
int v = e[i].y;
if (v == fa)
continue;
dfs1(v, x);
if (siz[v] > maxx)
son[x] = v, maxx = siz[v];
siz[x] += siz[v];
}
return;
}
void dfs2(int x, int fa, int _top) {
dfn[x] = ++tim;
top[x] = _top;
if (son[x])
dfs2(son[x], x, _top);
for (int i = head[x]; i; i = e[i].nex) {
int v = e[i].y;
if (v == fa || v == son[x])
continue;
dfs2(v, x, v);
}
return;
}
int lca(int x, int y) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]])
swap(x, y);
x = f[top[x]];
}
if (dep[x] < dep[y])
return x;
return y;
}
void pushup(int rt) {
t[rt].val = max(t[t[rt].l].val, t[t[rt].r].val);
if (t[t[rt].l].val >= t[t[rt].r].val)
t[rt].ans = t[t[rt].l].ans;
else
t[rt].ans = t[t[rt].r].ans;
}
int change(int rt, int l, int r, int pos, int num) {
if (!rt)
rt = ++cnt;
if (l == r) {
t[rt].ans = l;
t[rt].val += num;
return rt;
}
int mid = l + r >> 1;
if (pos <= mid)
t[rt].l = change(t[rt].l, l, mid, pos, num);
else
t[rt].r = change(t[rt].r, mid + 1, r, pos, num);
pushup(rt);
return rt;
}
int merge(int rt1, int rt2, int l, int r) {
if (!rt1 || !rt2)
return rt1 + rt2;
if (l == r) {
t[rt1].val += t[rt2].val;
return rt1;
}
int mid = l + r >> 1;
t[rt1].l = merge(t[rt1].l, t[rt2].l, l, mid);
t[rt1].r = merge(t[rt1].r, t[rt2].r, mid + 1, r);
pushup(rt1);
return rt1;
}
void dfs(int x, int fa) {
for (int i = head[x]; i; i = e[i].nex) {
int v = e[i].y;
if (v == fa)
continue;
dfs(v, x);
rt[x] = merge(rt[x], rt[v], 1, 100000);
}
if (t[rt[x]].val == 0)
ans[x] = 0;
else
ans[x] = t[rt[x]].ans;
return;
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i < n; i++) {
int x, y;
cin >> x >> y;
add(x, y);
add(y, x);
}
dfs1(1, 0), dfs2(1, 0, 1);
for (int i = 1; i <= m; ++i) {
int x, y, z;
cin >> x >> y >> z;
int l = lca(x, y);
rt[x] = change(rt[x], 1, 100000, z, 1);
rt[y] = change(rt[y], 1, 100000, z, 1);
rt[l] = change(rt[l], 1, 100000, z, -1);
rt[f[l]] = change(rt[f[l]], 1, 100000, z, -1);
}
dfs(1, 0);
for (int i = 1; i <= n; i++)
cout << ans[i] << endl;
return 0;
}
线段树分裂
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 200010;
int n, m, tot, cnt, seq = 1, op, x, y, z, bac[MAXN << 5], ch[MAXN << 5][2], rt[MAXN];
int val[MAXN << 5];
int newnode() {
return (cnt ? bac[cnt--] : ++tot);
}
void del(int p) {
bac[++cnt] = p, ch[p][0] = ch[p][1] = val[p] = 0;
return;
}
void add(int& p, int l, int r, int pos, int v) {
if (!p)
p = newnode();
val[p] += v;
if (l == r)
return;
int mid = (l + r) >> 1;
if (pos <= mid)
add(ch[p][0], l, mid, pos, v);
else
add(ch[p][1], mid + 1, r, pos, v);
return;
}
int query(int p, int l, int r, int xl, int xr) {
if (xr < l || r < xl)
return 0;
if (xl <= l && r <= xr)
return val[p];
int mid = (l + r) >> 1;
return query(ch[p][0], l, mid, xl, xr) + query(ch[p][1], mid + 1, r, xl, xr);
}
int kth(int p, int l, int r, int k) {
if (l == r)
return l;
int mid = (l + r) >> 1;
if (val[ch[p][0]] >= k)
return kth(ch[p][0], l, mid, k);
else
return kth(ch[p][1], mid + 1, r, k - val[ch[p][0]]);
}
int merge(int x, int y) {
if (!x || !y)
return x + y;
val[x] += val[y];
ch[x][0] = merge(ch[x][0], ch[y][0]);
ch[x][1] = merge(ch[x][1], ch[y][1]);
del(y);
return x;
}
void split(int x, int& y, int k) {
if (x == 0)
return;
y = newnode();
int v = val[ch[x][0]];
if (k > v)
split(ch[x][1], ch[y][1], k - v);
else
swap(ch[x][1], ch[y][1]);
if (k < v)
split(ch[x][0], ch[y][0], k);
val[y] = val[x] - k;
val[x] = k;
return;
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
scanf("%lld%lld", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%lld", &x);
add(rt[1], 1, n, i, x);
}
for (int i = 1; i <= m; i++) {
scanf("%lld", &op);
if (op == 0) {
scanf("%lld%lld%lld", &x, &y, &z);
int k1 = query(rt[x], 1, n, 1, z), k2 = query(rt[x], 1, n, y, z);
int tmp = 0;
split(rt[x], rt[++seq], k1 - k2);
split(rt[seq], tmp, k2);
rt[x] = merge(rt[x], tmp);
}
else if (op == 1) {
scanf("%lld%lld", &x, &y);
rt[x] = merge(rt[x], rt[y]);
}
else if (op == 2) {
scanf("%lld%lld%lld", &x, &y, &z);
add(rt[x], 1, n, z, y);
}
else if (op == 3) {
scanf("%lld%lld%lld", &x, &y, &z);
printf("%lld\n", query(rt[x], 1, n, y, z));
}
else if (op == 4) {
scanf("%lld%lld", &x, &y);
if (val[rt[x]] < y) {
printf("-1\n");
continue;
}
printf("%lld\n", kth(rt[x], 1, n, y));
}
}
return 0;
}
李超线段树
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
#define mp make_pair
#define db double
#define ls (rt << 1)
#define rs (rt << 1 | 1)
const db eps = 1e-10;
const int maxn = 1e6 + 10;
const int mod = 39989;
const int m = 40000;
const int Mod = 1e9;
const int inf = 0x3f3f3f3f;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
void Min(int& x, int y) {
x = (x < y) ? x : y;
}
void Max(int& x, int y) {
x = (x > y) ? x : y;
}
int add(int x, int y) {
return (x + y) >= mod ? (x + y - mod) : (x + y);
}
int sub(int x, int y) {
return (x < y) ? (x + mod - y) : (x - y);
}
void Add(int& x, int y) {
x = (x + y) >= mod ? (x + y - mod) : (x + y);
}
void Sub(int& x, int y) {
x = (x < y) ? (x - y + mod) : (x - y);
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
void Mul(int& x, int y) {
x = 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
int ans = 1;
while (y) {
if (y & 1)
ans = 1ll * x * ans % mod;
x = 1ll * x * x % mod, y >>= 1;
}
return ans;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, t[maxn << 2], tot, lst;
struct line {
db k, b;
} a[maxn];
db calc(line a, int x) {
return a.k * x + a.b;
}
void upd(int rt, int l, int r, int x, int y, int pos) {
int mid = (l + r) >> 1;
if (x <= l && r <= y) {
if (calc(a[pos], mid) > calc(a[t[rt]], mid) + eps)
swap(pos, t[rt]);
if (calc(a[pos], l) > calc(a[t[rt]], l) + eps ||
(calc(a[pos], l) == calc(a[t[rt]], l) && pos < t[rt]))
upd(ls, l, mid, x, y, pos);
if (calc(a[pos], r) > calc(a[t[rt]], r) + eps ||
(calc(a[pos], r) == calc(a[t[rt]], r) && pos < t[rt]))
upd(rs, mid + 1, r, x, y, pos);
return;
}
if (x <= mid)
upd(ls, l, mid, x, y, pos);
if (y > mid)
upd(rs, mid + 1, r, x, y, pos);
}
int query(int rt, int l, int r, int pos) {
if (l == r)
return t[rt];
int mid = (l + r) >> 1;
if (pos <= mid) {
int tmp = query(ls, l, mid, pos);
db num1 = calc(a[tmp], pos), num2 = calc(a[t[rt]], pos);
if (num1 > num2 + eps)
return tmp;
if (num1 + eps < num2)
return t[rt];
return min(tmp, t[rt]);
}
else {
int tmp = query(rs, mid + 1, r, pos);
db num1 = calc(a[tmp], pos), num2 = calc(a[t[rt]], pos);
if (num1 > num2 + eps)
return tmp;
if (num1 + eps < num2)
return t[rt];
return min(tmp, t[rt]);
}
}
signed main() {
openfile();
n = read();
while (n--) {
cerr << n << endl;
int op = read();
if (!op) {
int k = (read() + lst - 1) % mod + 1;
printf("%lld\n", (lst = query(1, 1, m, k)));
}
else {
int x0 = (read() + lst - 1) % mod + 1, y0 = (read() + lst - 1) % Mod + 1,
x1 = (read() + lst - 1) % mod + 1, y1 = (read() + lst - 1) % Mod + 1;
if (x0 > x1)
swap(x0, x1), swap(y0, y1);
if (x0 == x1)
a[++tot] = line{0, (db)max(y1, y0)};
else
a[++tot] = line{1.0 * (y1 - y0) / (x1 - x0), y0 - 1.0 * (y1 - y0) / (x1 - x0) * x0};
upd(1, 1, m, x0, x1, tot);
}
}
return 0;
}
扫描线面积
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 2e6 + 10;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, tot, cnt, rk[maxn];
int t[maxn], tc[maxn];
struct line {
int x, y, yy, z;
} e[maxn << 1];
bool cmp(line a, line b) {
if (a.x == b.x)
return a.z > b.z;
return a.x < b.x;
}
void pushup(int rt, int l, int r) {
if (!tc[rt])
t[rt] = t[rt << 1] + t[rt << 1 | 1];
else
t[rt] = rk[r + 1] - rk[l];
}
void add(int rt, int l, int r, int x, int y, int val) {
if (x <= l && r <= y) {
tc[rt] += val;
pushup(rt, l, r);
return;
}
int mid = (l + r) >> 1;
if (x <= mid)
add(rt << 1, l, mid, x, y, val);
if (y > mid)
add(rt << 1 | 1, mid + 1, r, x, y, val);
pushup(rt, l, r);
}
signed main() {
openfile();
n = read();
for (int i = 1; i <= n; i++) {
int x = read(), y = read(), xx = read(), yy = read();
e[++tot] = {x, y, yy, 1};
e[++tot] = {xx, y, yy, -1};
rk[++cnt] = y, rk[++cnt] = yy;
}
sort(rk + 1, rk + 1 + cnt);
cnt = unique(rk + 1, rk + 1 + cnt) - rk - 1;
for (int i = 1; i <= n * 2; i++) {
e[i].y = lower_bound(rk + 1, rk + 1 + cnt, e[i].y) - rk;
e[i].yy = lower_bound(rk + 1, rk + 1 + cnt, e[i].yy) - rk;
}
sort(e + 1, e + 1 + 2 * n, cmp);
int ans = 0;
for (int i = 1; i < 2 * n; i++) {
add(1, 1, n * 2, e[i].y, e[i].yy - 1, e[i].z);
ans += (e[i + 1].x - e[i].x) * t[1];
}
cout << ans << endl;
return 0;
}
可持久化线段树
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
#define mp make_pair
const int maxn = 2e5 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
int add(int x, int y) {
x += y;
return x >= mod ? x - mod : x;
}
int sub(int x, int y) {
x -= y;
return x < 0 ? x + mod : x;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, m, a[maxn], b[maxn], cnt;
int t[maxn << 5], tot, rt[maxn << 5], ls[maxn << 5], rs[maxn << 5];
int build(int l, int r) {
int rt = ++tot, mid = (l + r) >> 1;
if (l == r)
return rt;
ls[rt] = build(l, mid), rs[rt] = build(mid + 1, r);
return rt;
}
int add(int lst, int l, int r, int pos, int x = 1) {
int rt = ++tot;
t[rt] = t[lst] + x, ls[rt] = ls[lst], rs[rt] = rs[lst];
if (l == r)
return rt;
int mid = (l + r) >> 1;
if (pos <= mid)
ls[rt] = add(ls[lst], l, mid, pos, x);
else
rs[rt] = add(rs[lst], mid + 1, r, pos, x);
return rt;
}
int ask(int lr, int rr, int l, int r, int k) {
if (l == r)
return b[l];
int mid = (l + r) >> 1;
int num = t[ls[rr]] - t[ls[lr]];
// cout << lr << ' ' << rr << ' ' << l << ' ' << r << ' ' << k << ' ' << num << endl;
if (num >= k)
return ask(ls[lr], ls[rr], l, mid, k);
return ask(rs[lr], rs[rr], mid + 1, r, k - num);
}
signed main() {
openfile();
n = read(), m = read();
for (int i = 1; i <= n; i++)
a[i] = b[i] = read();
sort(b + 1, b + 1 + n);
cnt = unique(b + 1, b + 1 + n) - b - 1;
rt[0] = build(1, cnt);
for (int i = 1; i <= n; i++) {
a[i] = lower_bound(b + 1, b + 1 + cnt, a[i]) - b;
rt[i] = add(rt[i - 1], 1, cnt, a[i]);
}
while (m--) {
int l = read(), r = read(), k = read();
printf("%lld\n", ask(rt[l - 1], rt[r], 1, cnt, k));
}
cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
return 0;
}
zkw线段树
// by Judge
#include <cstdio>
#include <iostream>
using namespace std;
const int M = 1e5 + 111;
// #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1 << 21], *p1 = buf, *p2 = buf;
inline int read() {
int x = 0, f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
char sr[1 << 21], z[20];
int C = -1, Z;
inline void Ot() {
fwrite(sr, 1, C + 1, stdout), C = -1;
}
inline void print(int x) {
if (C > 1 << 20)
Ot();
if (x < 0)
sr[++C] = 45, x = -x;
while (z[++Z] = x % 10 + 48, x /= 10)
;
while (sr[++C] = z[Z], --Z)
;
sr[++C] = '\n';
}
int n, m, q;
int sum[M << 2], mn[M << 2], mx[M << 2], add[M << 2];
inline void build() {
for (m = 1; m <= n; m <<= 1)
;
for (int i = m + 1; i <= m + n; ++i)
sum[i] = mn[i] = mx[i] = read();
for (int i = m - 1; i; --i) {
sum[i] = sum[i << 1] + sum[i << 1 | 1];
mn[i] = min(mn[i << 1], mn[i << 1 | 1]), mn[i << 1] -= mn[i], mn[i << 1 | 1] -= mn[i];
mx[i] = max(mx[i << 1], mx[i << 1 | 1]), mx[i << 1] -= mx[i], mx[i << 1 | 1] -= mx[i];
}
}
inline void update_node(int x, int v, int A = 0) {
x += m, mx[x] += v, mn[x] += v, sum[x] += v;
for (; x > 1; x >>= 1) {
sum[x] += v;
A = min(mn[x], mn[x ^ 1]);
mn[x] -= A, mn[x ^ 1] -= A, mn[x >> 1] += A;
A = max(mx[x], mx[x ^ 1]), mx[x] -= A, mx[x ^ 1] -= A, mx[x >> 1] += A;
}
}
inline void update_part(int s, int t, int v) {
int A = 0, lc = 0, rc = 0, len = 1;
for (s += m - 1, t += m + 1; s ^ t ^ 1; s >>= 1, t >>= 1, len <<= 1) {
if (s & 1 ^ 1)
add[s ^ 1] += v, lc += len, mn[s ^ 1] += v, mx[s ^ 1] += v;
if (t & 1)
add[t ^ 1] += v, rc += len, mn[t ^ 1] += v, mx[t ^ 1] += v;
sum[s >> 1] += v * lc, sum[t >> 1] += v * rc;
A = min(mn[s], mn[s ^ 1]), mn[s] -= A, mn[s ^ 1] -= A, mn[s >> 1] += A,
A = min(mn[t], mn[t ^ 1]), mn[t] -= A, mn[t ^ 1] -= A, mn[t >> 1] += A;
A = max(mx[s], mx[s ^ 1]), mx[s] -= A, mx[s ^ 1] -= A, mx[s >> 1] += A,
A = max(mx[t], mx[t ^ 1]), mx[t] -= A, mx[t ^ 1] -= A, mx[t >> 1] += A;
}
for (lc += rc; s; s >>= 1) {
sum[s >> 1] += v * lc;
A = min(mn[s], mn[s ^ 1]), mn[s] -= A, mn[s ^ 1] -= A, mn[s >> 1] += A,
A = max(mx[s], mx[s ^ 1]), mx[s] -= A, mx[s ^ 1] -= A, mx[s >> 1] += A;
}
}
inline int query_node(int x, int ans = 0) {
for (x += m; x; x >>= 1)
ans += mn[x];
return ans;
}
inline int query_sum(int s, int t) {
int lc = 0, rc = 0, len = 1, ans = 0;
for (s += m - 1, t += m + 1; s ^ t ^ 1; s >>= 1, t >>= 1, len <<= 1) {
if (s & 1 ^ 1)
ans += sum[s ^ 1] + len * add[s ^ 1], lc += len;
if (t & 1)
ans += sum[t ^ 1] + len * add[t ^ 1], rc += len;
if (add[s >> 1])
ans += add[s >> 1] * lc;
if (add[t >> 1])
ans += add[t >> 1] * rc;
}
for (lc += rc, s >>= 1; s; s >>= 1)
if (add[s])
ans += add[s] * lc;
return ans;
}
inline int query_min(int s, int t, int L = 0, int R = 0, int ans = 0) {
if (s == t)
return query_node(s);
for (s += m, t += m; s ^ t ^ 1; s >>= 1, t >>= 1) {
L += mn[s], R += mn[t];
if (s & 1 ^ 1)
L = min(L, mn[s ^ 1]);
if (t & 1)
R = min(R, mn[t ^ 1]);
}
for (ans = min(L, R), s >>= 1; s; s >>= 1)
ans += mn[s];
return ans;
}
inline int query_max(int s, int t, int L = 0, int R = 0, int ans = 0) {
if (s == t)
return query_node(s);
for (s += m, t += m; s ^ t ^ 1; s >>= 1, t >>= 1) {
L += mx[s], R += mx[t];
if (s & 1 ^ 1)
L = max(L, mx[s ^ 1]);
if (t & 1)
R = max(R, mx[t ^ 1]);
}
for (ans = max(L, R), s >>= 1; s; s >>= 1)
ans += mx[s];
return ans;
}
signed main() {
return 0;
}
普通平衡树(splay)
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
#define mp make_pair
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
int add(int x, int y) {
x += y;
return x >= mod ? x - mod : x;
}
int sub(int x, int y) {
x -= y;
return x < 0 ? x + mod : x;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
struct Splay {
int ch[maxn][2], tot, fa[maxn], val[maxn], cnt[maxn], siz[maxn], rt;
int check(int x, int y) {
return ch[y][1] == x;
}
void pushup(int x) {
siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];
}
void rotate(int x) {
int y = fa[x], z = fa[y];
int k = check(x, y), kk = check(y, z);
ch[z][kk] = x, fa[x] = z;
ch[y][k] = ch[x][k ^ 1], fa[ch[x][k ^ 1]] = y;
fa[y] = x, ch[x][k ^ 1] = y;
pushup(y), pushup(x);
}
void splay(int x, int o) {
while (fa[x] != o) {
int y = fa[x], z = fa[y];
if (z != o)
(check(x, y) ^ check(y, z)) ? rotate(x) : rotate(y);
rotate(x);
}
if (!o)
rt = x;
}
void insert(int x) {
int u = rt, ff = 0;
while (u && val[u] != x)
ff = u, u = ch[u][x > val[u]];
if (val[u] == x)
cnt[u]++;
else {
u = ++tot;
if (ff)
ch[ff][x > val[ff]] = u;
fa[u] = ff;
val[u] = x, cnt[u] = siz[u] = 1;
}
splay(u, 0);
}
int rk(int x) {
int u = rt;
if (!u)
return -1;
while (x != val[u] && ch[u][x > val[u]])
u = ch[u][x > val[u]];
splay(u, 0);
return siz[ch[u][0]] + 1;
}
int pre(int x) {
rk(x);
int u = rt;
if (val[u] < x)
return u;
u = ch[u][0];
while (ch[u][1])
u = ch[u][1];
return u;
}
int nex(int x) {
rk(x);
int u = rt;
if (val[u] > x)
return u;
u = ch[u][1];
while (ch[u][0])
u = ch[u][0];
return u;
}
void del(int x) {
int l = pre(x), r = nex(x);
splay(l, 0), splay(r, l);
int u = ch[r][0];
if (cnt[u] - 1)
cnt[u]--, splay(u, 0);
else
ch[r][0] = 0, splay(r, 0);
}
int kth(int x) {
int u = rt;
while (1) {
int v = ch[u][0];
if (siz[v] + cnt[u] < x)
x -= siz[v] + cnt[u], u = ch[u][1];
else if (x <= siz[v])
u = v;
else
return val[u];
}
}
} t;
signed main() {
openfile();
int n = read();
t.insert(-inf), t.insert(inf);
while (n--) {
int op = read(), x = read();
if (op == 1)
t.insert(x);
if (op == 2)
t.del(x);
if (op == 3)
printf("%lld\n", t.rk(x) - 1);
if (op == 4)
printf("%lld\n", t.kth(x + 1));
if (op == 5)
printf("%lld\n", t.val[t.pre(x)]);
if (op == 6)
printf("%lld\n", t.val[t.nex(x)]);
}
cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
return 0;
}
普通平衡树(FHQ)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
#define mp make_pair
#define db double
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
void Min(int& x, int y) {
x = (x < y) ? x : y;
}
void Max(int& x, int y) {
x = (x > y) ? x : y;
}
int add(int x, int y) {
return (x + y) >= mod ? (x + y - mod) : (x + y);
}
int sub(int x, int y) {
return (x < y) ? (x + mod - y) : (x - y);
}
void Add(int& x, int y) {
x = (x + y) >= mod ? (x + y - mod) : (x + y);
}
void Sub(int& x, int y) {
x = (x < y) ? (x - y + mod) : (x - y);
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
void Mul(int& x, int y) {
x = 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
int ans = 1;
while (y) {
if (y & 1)
ans = 1ll * x * ans % mod;
x = 1ll * x * x % mod, y >>= 1;
}
return ans;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
mt19937 rd(time(0));
int n, tot, rt, val[maxn], pri[maxn], ls[maxn], rs[maxn], siz[maxn];
void pushup(int x) {
siz[x] = siz[ls[x]] + siz[rs[x]] + 1;
}
int nd(int x) {
pri[++tot] = rd(), val[tot] = x, siz[tot] = 1;
return tot;
}
void split_siz(int rt, int k, int& x, int& y) {
if (!rt)
return x = y = 0, void();
if (siz[ls[rt]] >= k) {
y = rt;
split_siz(ls[rt], k, x, ls[rt]);
pushup(rt);
}
else {
x = rt;
split_siz(rs[rt], k - siz[ls[rt]] - 1, rs[rt], y);
pushup(rt);
}
}
void split_num(int rt, int v, int& x, int& y) {
if (!rt)
return x = y = 0, void();
if (val[rt] <= v)
x = rt, split_num(rs[x], v, rs[x], y);
else
y = rt, split_num(ls[y], v, x, ls[y]);
pushup(rt);
}
int merge(int x, int y) {
if (!x || !y)
return (x | y);
if (pri[x] < pri[y]) {
rs[x] = merge(rs[x], y);
return pushup(x), x;
}
else {
ls[y] = merge(x, ls[y]);
return pushup(y), y;
}
}
void ins(int v) {
int x, y;
cerr << v << endl;
split_num(rt, v - 1, x, y);
rt = merge(merge(x, nd(v)), y);
}
void del(int v) {
int x, y, z, k;
split_num(rt, v, y, z);
split_num(y, v - 1, x, y);
y = merge(ls[y], rs[y]);
rt = merge(merge(x, y), z);
}
int rk(int v) {
int x, y, ans;
split_num(rt, v - 1, x, y);
ans = siz[x] + 1;
rt = merge(x, y);
return ans;
}
int find(int k) {
int x, y, z, ans;
split_siz(rt, k, y, z);
split_siz(y, k - 1, x, y);
ans = val[y];
rt = merge(merge(x, y), z);
return ans;
}
int lst(int v) {
int x, y, ans;
split_num(rt, v - 1, x, y);
int u = x;
while (rs[u])
u = rs[u];
ans = val[u];
rt = merge(x, y);
return ans;
}
int nex(int v) {
int x, y, ans;
split_num(rt, v, x, y);
int u = y;
while (ls[u])
u = ls[u];
ans = val[u];
rt = merge(x, y);
return ans;
}
signed main() {
openfile();
n = read();
for (int i = 1; i <= n; i++) {
int op = read(), x = read();
if (op == 1)
ins(x);
if (op == 2)
del(x);
if (op == 3)
printf("%d\n", rk(x));
if (op == 4)
printf("%d\n", find(x));
if (op == 5)
printf("%d\n", lst(x));
if (op == 6)
printf("%d\n", nex(x));
cerr << i << endl;
}
return 0;
}
文艺平衡树(splay)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
#define mp make_pair
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const ll inf = 0x3f3f3f3f3f3f3f3f;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
int add(ll x, ll y) {
x += y;
return x >= mod ? x - mod : x;
}
int sub(int x, int y) {
x -= y;
return x < 0 ? x + mod : x;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, m;
int a[maxn];
struct Splay {
int ch[maxn][2], tot, rt, fa[maxn], tag[maxn], siz[maxn], val[maxn];
bool check(int x, int y) {
return ch[y][1] == x;
}
void pushup(int x) {
siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
}
void rotate(int x) {
int y = fa[x], z = fa[y];
int k = check(x, y), kk = check(y, z);
fa[x] = z, ch[z][kk] = x;
fa[ch[x][k ^ 1]] = y, ch[y][k] = ch[x][k ^ 1];
fa[y] = x, ch[x][k ^ 1] = y;
pushup(x), pushup(y);
}
void splay(int x, int o) {
while (fa[x] != o) {
int y = fa[x], z = fa[y];
if (z != o)
(check(x, y) ^ check(y, z)) ? rotate(x) : rotate(y);
rotate(x);
}
if (!o)
rt = x;
}
void rev(int x) {
tag[x] ^= 1;
swap(ch[x][0], ch[x][1]);
}
int build(int f, int l, int r) {
if (r < l)
return 0;
int mid = (l + r) >> 1, u = ++tot;
val[u] = mid, fa[u] = f, siz[u] = 1;
ch[u][0] = build(u, l, mid - 1);
ch[u][1] = build(u, mid + 1, r);
pushup(u);
return u;
}
void pushdown(int x) {
if (tag[x]) {
rev(ch[x][0]), rev(ch[x][1]);
tag[x] = 0;
}
}
int find(int x) {
x++;
int u = rt;
while (1) {
pushdown(u);
int v = ch[u][0];
if (siz[v] + 1 < x)
x -= siz[v] + 1, u = ch[u][1];
else if (siz[v] >= x)
u = v;
else
return u;
}
}
void rever(int l, int r) {
int x = find(l - 1), y = find(r + 1);
splay(x, 0), splay(y, x);
rev(ch[y][0]);
}
void print(int x) {
if (!x)
return;
pushdown(x);
print(ch[x][0]);
if (val[x] && val[x] <= n)
printf("%d ", val[x]);
print(ch[x][1]);
}
} t;
signed main() {
openfile();
n = read(), m = read();
t.rt = t.build(0, 0, n + 1);
while (m--) {
int x = read(), y = read();
t.rever(x, y);
}
t.print(t.rt);
cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
return 0;
}
文艺平衡树(FHQ)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
#define mp make_pair
#define db double
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
void Min(int& x, int y) {
x = (x < y) ? x : y;
}
void Max(int& x, int y) {
x = (x > y) ? x : y;
}
int add(int x, int y) {
return (x + y) >= mod ? (x + y - mod) : (x + y);
}
int sub(int x, int y) {
return (x < y) ? (x + mod - y) : (x - y);
}
void Add(int& x, int y) {
x = (x + y) >= mod ? (x + y - mod) : (x + y);
}
void Sub(int& x, int y) {
x = (x < y) ? (x - y + mod) : (x - y);
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
void Mul(int& x, int y) {
x = 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
int ans = 1;
while (y) {
if (y & 1)
ans = 1ll * x * ans % mod;
x = 1ll * x * x % mod, y >>= 1;
}
return ans;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, m, a[maxn];
int val[maxn], rev[maxn], siz[maxn], pri[maxn], ls[maxn], rs[maxn];
int tot, rt;
mt19937 rd(time(0));
int newnode(int v) {
++tot;
val[tot] = v, siz[tot] = 1, pri[tot] = rd();
return tot;
}
void fan(int rt) {
if (rt)
swap(ls[rt], rs[rt]), rev[rt] ^= 1;
}
void pushdown(int rt) {
if (rev[rt])
fan(ls[rt]), fan(rs[rt]), rev[rt] = 0;
}
void pushup(int rt) {
siz[rt] = siz[ls[rt]] + siz[rs[rt]] + 1;
}
void split(int rt, int k, int& x, int& y) {
if (!rt)
return x = y = 0, void();
pushdown(rt);
if (siz[ls[rt]] >= k)
y = rt, split(ls[rt], k, x, ls[rt]);
else
x = rt, split(rs[rt], k - siz[ls[rt]] - 1, rs[rt], y);
pushup(rt);
}
int merge(int x, int y) {
if (!x || !y)
return (x | y);
pushdown(x), pushdown(y);
if (pri[x] < pri[y]) {
rs[x] = merge(rs[x], y);
pushup(x);
return x;
}
else {
ls[y] = merge(x, ls[y]);
pushup(y);
return y;
}
}
void chu(int rt) {
if (!rt)
return;
pushdown(rt);
chu(ls[rt]), printf("%d ", val[rt]), chu(rs[rt]);
}
signed main() {
openfile();
n = read(), m = read();
for (int i = 1; i <= n; i++)
rt = merge(rt, newnode(i));
while (m--) {
int l = read(), r = read(), x, y, z;
split(rt, r, y, z);
split(y, l - 1, x, y);
fan(y);
rt = merge(merge(x, y), z);
}
chu(rt);
return 0;
}
KDT
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
using namespace std;
constexpr int MAXN = 200010;
int n, d[MAXN], lc[MAXN], rc[MAXN];
double ans = 2e18;
struct node {
double x, y;
} s[MAXN];
double L[MAXN], R[MAXN], D[MAXN], U[MAXN];
double dist(int a, int b) {
return (s[a].x - s[b].x) * (s[a].x - s[b].x) +
(s[a].y - s[b].y) * (s[a].y - s[b].y);
}
bool cmp1(node a, node b) { return a.x < b.x; }
bool cmp2(node a, node b) { return a.y < b.y; }
void maintain(int x) {
L[x] = R[x] = s[x].x;
D[x] = U[x] = s[x].y;
if (lc[x])
L[x] = min(L[x], L[lc[x]]), R[x] = max(R[x], R[lc[x]]),
D[x] = min(D[x], D[lc[x]]), U[x] = max(U[x], U[lc[x]]);
if (rc[x])
L[x] = min(L[x], L[rc[x]]), R[x] = max(R[x], R[rc[x]]),
D[x] = min(D[x], D[rc[x]]), U[x] = max(U[x], U[rc[x]]);
}
int build(int l, int r) {
if (l > r) return 0;
if (l == r) {
maintain(l);
return l;
}
int mid = (l + r) >> 1;
double avx = 0, avy = 0, vax = 0, vay = 0; // average variance
for (int i = l; i <= r; i++) avx += s[i].x, avy += s[i].y;
avx /= (double)(r - l + 1);
avy /= (double)(r - l + 1);
for (int i = l; i <= r; i++)
vax += (s[i].x - avx) * (s[i].x - avx),
vay += (s[i].y - avy) * (s[i].y - avy);
if (vax >= vay)
d[mid] = 1, nth_element(s + l, s + mid, s + r + 1, cmp1);
else
d[mid] = 2, nth_element(s + l, s + mid, s + r + 1, cmp2);
lc[mid] = build(l, mid - 1), rc[mid] = build(mid + 1, r);
maintain(mid);
return mid;
}
double f(int a, int b) {
double ret = 0;
if (L[b] > s[a].x) ret += (L[b] - s[a].x) * (L[b] - s[a].x);
if (R[b] < s[a].x) ret += (s[a].x - R[b]) * (s[a].x - R[b]);
if (D[b] > s[a].y) ret += (D[b] - s[a].y) * (D[b] - s[a].y);
if (U[b] < s[a].y) ret += (s[a].y - U[b]) * (s[a].y - U[b]);
return ret;
}
void query(int l, int r, int x) {
if (l > r) return;
int mid = (l + r) >> 1;
if (mid != x) ans = min(ans, dist(x, mid));
if (l == r) return;
double distl = f(x, lc[mid]), distr = f(x, rc[mid]);
if (distl < ans && distr < ans) {
if (distl < distr) {
query(l, mid - 1, x);
if (distr < ans) query(mid + 1, r, x);
} else {
query(mid + 1, r, x);
if (distl < ans) query(l, mid - 1, x);
}
} else {
if (distl < ans) query(l, mid - 1, x);
if (distr < ans) query(mid + 1, r, x);
}
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> n;
for (int i = 1; i <= n; i++) cin >> s[i].x >> s[i].y;
build(1, n);
for (int i = 1; i <= n; i++) query(1, n, i);
cout << fixed << setprecision(4) << sqrt(ans) << '\n';
return 0;
}
笛卡尔树
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
#define mp make_pair
#define db double
const int maxn = 1e7 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
void Min(int& x, int y) {
x = (x < y) ? x : y;
}
void Max(int& x, int y) {
x = (x > y) ? x : y;
}
int add(int x, int y) {
return (x + y) >= mod ? (x + y - mod) : (x + y);
}
int sub(int x, int y) {
return (x < y) ? (x + mod - y) : (x - y);
}
void Add(int& x, int y) {
x = (x + y) >= mod ? (x + y - mod) : (x + y);
}
void Sub(int& x, int y) {
x = (x < y) ? (x - y + mod) : (x - y);
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
void Mul(int& x, int y) {
x = 1ll * x * y % mod;
}
int qpow(int x, int y = mod - 2) {
int ans = 1;
while (y) {
if (y & 1)
ans = 1ll * x * ans % mod;
x = 1ll * x * x % mod, y >>= 1;
}
return ans;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, a[maxn];
int sta[maxn], top, ls[maxn], rs[maxn], fa[maxn];
signed main() {
openfile();
n = read();
for (int i = 1; i <= n; i++)
a[i] = read();
for (int i = 1; i <= n; i++) {
int k = top;
while (k && a[sta[k]] > a[i])
k--;
if (k)
rs[sta[k]] = i, fa[i] = sta[k];
if (k < top)
ls[i] = sta[k + 1], fa[sta[k + 1]] = i;
top = k;
sta[++top] = i;
}
ll ans = 0;
for (int i = 1; i <= n; i++)
ans ^= 1ll * i * (ls[i] + 1);
cout << ans << ' ', ans = 0;
for (int i = 1; i <= n; i++)
ans ^= 1ll * i * (rs[i] + 1);
cout << ans << endl;
return 0;
}
重剖
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ls (rt << 1)
#define rs (rt << 1 | 1)
#define pii pair<int, int>
#define mp make_pair
const int maxn = 1e6 + 10;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n, m, rt, mod;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
int add(ll x, ll y) {
x += y;
return x >= mod ? x - mod : x;
}
int sub(int x, int y) {
x -= y;
return x < 0 ? x + mod : x;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int dfn[maxn], siz[maxn], top[maxn], fa[maxn], son[maxn], tim, dep[maxn];
int tag[maxn << 2], t[maxn << 2], a[maxn];
vector<int> e[maxn];
void dfs1(int x, int _fa) {
siz[x] = 1, fa[x] = _fa;
dep[x] = dep[_fa] + 1;
for (auto v : e[x]) {
if (v == _fa)
continue;
dfs1(v, x);
siz[x] += siz[v];
if (siz[v] > siz[son[x]])
son[x] = v;
}
}
void pushdown(int rt, int l, int r) {
if (tag[rt]) {
int x = tag[rt], mid = (l + r) >> 1;
t[ls] = add(t[ls], 1ll * x * (mid - l + 1) % mod),
t[rs] = add(t[rs], 1ll * x * (r - mid) % mod), tag[rt] = 0;
tag[ls] = add(tag[ls], x), tag[rs] = add(tag[rs], x);
}
}
void change(int rt, int l, int r, int pos, int x) {
if (l == r) {
t[rt] = x;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid)
change(ls, l, mid, pos, x);
else
change(rs, mid + 1, r, pos, x);
t[rt] = add(t[ls], t[rs]);
}
void dfs2(int x, int tp) {
dfn[x] = ++tim, top[x] = tp;
change(1, 1, n, dfn[x], a[x]);
if (son[x])
dfs2(son[x], tp);
for (auto v : e[x]) {
if (v == fa[x] || v == son[x])
continue;
dfs2(v, v);
}
}
void add(int rt, int l, int r, int x, int y, int z) {
if (x <= l && r <= y) {
t[rt] = add(t[rt], 1ll * z * (r - l + 1) % mod);
tag[rt] = add(tag[rt], z);
return;
}
pushdown(rt, l, r);
int mid = (l + r) >> 1;
if (x <= mid)
add(ls, l, mid, x, y, z);
if (y > mid)
add(rs, mid + 1, r, x, y, z);
t[rt] = add(t[ls], t[rs]);
}
int ask(int rt, int l, int r, int x, int y) {
if (x <= l && r <= y)
return t[rt];
pushdown(rt, l, r);
int ans = 0, mid = l + r >> 1;
if (x <= mid)
ans = add(ans, ask(ls, l, mid, x, y));
if (y > mid)
ans = add(ans, ask(rs, mid + 1, r, x, y));
return ans;
}
void change_lu(int x, int y, int z) {
while (top[x] != top[y]) {
if (dep[top[x]] > dep[top[y]])
swap(x, y);
add(1, 1, n, dfn[top[y]], dfn[y], z);
y = fa[top[y]];
// cout << dfn[top[y]] << ' ' << dfn[y] << ' ' << z << endl;
}
if (dep[x] > dep[y])
swap(x, y);
add(1, 1, n, dfn[x], dfn[y], z);
// cout << dfn[x] << ' ' << dfn[y] << ' ' << z << endl;
}
int ask_lu(int x, int y) {
int ans = 0;
while (top[x] != top[y]) {
if (dep[top[x]] > dep[top[y]])
swap(x, y);
ans = add(ans, ask(1, 1, n, dfn[top[y]], dfn[y]));
y = fa[top[y]];
}
if (dep[x] > dep[y])
swap(x, y);
ans = add(ans, ask(1, 1, n, dfn[x], dfn[y]));
return ans;
}
void change_zi(int x, int y) {
add(1, 1, n, dfn[x], dfn[x] + siz[x] - 1, y);
}
int ask_zi(int x) {
return ask(1, 1, n, dfn[x], dfn[x] + siz[x] - 1);
}
signed main() {
openfile();
n = read(), m = read(), rt = read(), mod = read();
for (int i = 1; i <= n; i++)
a[i] = read();
for (int i = 1; i < n; i++) {
int x = read(), y = read();
e[x].push_back(y), e[y].push_back(x);
}
dfs1(rt, 0), dfs2(rt, rt);
while (m--) {
int op = read(), x = read(), y, z;
if (op == 1) {
y = read(), z = read();
change_lu(x, y, z);
}
if (op == 2)
y = read(), printf("%d\n", ask_lu(x, y));
if (op == 3)
y = read(), change_zi(x, y);
if (op == 4)
printf("%d\n", ask_zi(x));
}
cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
return 0;
}
长剖
#include <algorithm>
#include <iostream>
using namespace std;
constexpr int N = 1000005;
struct edge {
int to, next;
} e[N * 2];
int head[N], tot, n;
int d[N], fa[N], mx[N];
int *f[N], g[N], mxp[N];
int dfn[N];
void add(int x, int y) {
e[++tot] = edge{y, head[x]};
head[x] = tot;
}
void dfs1(int x) { // 第一次插入一个1
d[x] = 1;
for (int i = head[x]; i; i = e[i].next)
if (e[i].to != fa[x]) {
fa[e[i].to] = x;
dfs1(e[i].to);
d[x] = max(d[x], d[e[i].to] + 1);
if (d[e[i].to] > d[mx[x]]) mx[x] = e[i].to;
}
}
void dfs2(int x) { // 第二次合并
dfn[x] = ++*dfn;
f[x] = g + dfn[x];
if (mx[x]) dfs2(mx[x]);
for (int i = head[x]; i; i = e[i].next)
if (e[i].to != fa[x] && e[i].to != mx[x]) dfs2(e[i].to);
}
void getans(int x) { // 暴力合并算答案
if (mx[x]) {
getans(mx[x]);
mxp[x] = mxp[mx[x]] + 1;
}
f[x][0] = 1;
if (f[x][mxp[x]] <= 1) mxp[x] = 0;
for (int i = head[x]; i; i = e[i].next)
if (e[i].to != fa[x] && e[i].to != mx[x]) {
getans(e[i].to);
int len = d[e[i].to];
for (int j = 0; j <= len - 1; j++) {
f[x][j + 1] += f[e[i].to][j];
if (f[x][j + 1] > f[x][mxp[x]]) mxp[x] = j + 1;
if (f[x][j + 1] == f[x][mxp[x]] && j + 1 < mxp[x]) mxp[x] = j + 1;
}
}
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> n;
for (int i = 1; i < n; i++) {
int x, y;
cin >> x >> y;
add(x, y);
add(y, x);
}
dfs1(1);
dfs2(1);
getans(1);
for (int i = 1; i <= n; i++) cout << mxp[i] << '\n';
}
LCT
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
#define mp make_pair
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
int add(int x, int y) {
x += y;
return x >= mod ? x - mod : x;
}
int sub(int x, int y) {
x -= y;
return x < 0 ? x + mod : x;
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, m;
struct LCT {
int fa[maxn], ch[maxn][2], res[maxn], val[maxn], q[maxn], top, rev[maxn];
// res是
// 异或和,val每个点的值,q是splay时用于下传标记的数组,rev是翻转标记,fa就是父亲,非splay的根节点的fa就是树上的father,根节点的fa是整条链的father,ch是splay上的两个儿子
bool isroot(int x) {
return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
}
void pushdown(int x) {
if (rev[x]) {
rev[x] ^= 1, rev[ch[x][0]] ^= 1, rev[ch[x][1]] ^= 1;
swap(ch[x][0], ch[x][1]);
}
}
bool check(int x, int y) {
return ch[y][1] == x;
}
void pushup(int x) {
res[x] = val[x] ^ res[ch[x][0]] ^ res[ch[x][1]];
}
void rotate(int x) {
int y = fa[x], z = fa[y], l = check(x, y), r = l ^ 1;
if (!isroot(y))
ch[z][check(y, z)] = x;
fa[x] = z, fa[ch[x][r]] = y, ch[y][l] = ch[x][r];
fa[y] = x, ch[x][r] = y;
pushup(y), pushup(x);
}
void splay(int x) {
top = 1, q[top] = x;
int y = x;
while (!isroot(y))
q[++top] = fa[y], y = fa[y];
for (int i = top; i; i--)
pushdown(q[i]);
while (!isroot(x)) {
int y = fa[x], z = fa[y];
if (!isroot(y))
((check(x, y) ^ check(y, z)) ? rotate(x) : rotate(y));
rotate(x);
}
}
void access(int x) {
for (int t = 0; x; t = x, x = fa[x])
splay(x), ch[x][1] = t, pushup(x);
}
void makeroot(int x) {
access(x);
splay(x);
rev[x] ^= 1;
}
int findroot(int x) {
access(x), splay(x);
while (ch[x][0])
x = ch[x][0];
return x;
}
void split(int x, int y) {
makeroot(x);
access(y);
splay(y);
}
void cut(int x, int y) {
split(x, y);
if (ch[y][0] == x)
ch[y][0] = 0, fa[x] = 0;
}
void link(int x, int y) {
makeroot(x);
if (findroot(y) == x)
return;
fa[x] = y;
}
int ask(int x, int y) {
split(x, y);
return res[y];
}
void change(int x, int y) {
access(x), splay(x);
val[x] = y, pushup(x);
}
} lct;
signed main() {
// ios::sync_with_stdio(false);
// cin.tie(0);
openfile();
n = read(), m = read();
for (int i = 1; i <= n; i++)
lct.val[i] = lct.res[i] = read();
while (m--) {
int op = read(), x = read(), y = read();
if (op == 0)
printf("%d\n", lct.ask(x, y));
if (op == 1)
lct.link(x, y);
if (op == 2)
lct.cut(x, y);
if (op == 3)
lct.change(x, y);
}
return 0;
}
dsu on tree
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e6 + 10;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n;
int a[maxn], ans[maxn], son[maxn], siz[maxn], f[maxn], cnt[maxn], now, mx;
vector<int> e[maxn];
void dfs(int x, int fa) {
f[x] = fa;
siz[x] = 1;
for (auto v : e[x]) {
if (v == fa)
continue;
dfs(v, x);
siz[x] += siz[v];
if (siz[v] > siz[son[x]])
son[x] = v;
}
}
void clear(int x) {
mx = now = 0;
cnt[a[x]] = 0;
for (auto v : e[x])
if (v != f[x])
clear(v);
}
void solve(int x) {
cnt[a[x]]++;
if (cnt[a[x]] == mx)
now += a[x];
if (cnt[a[x]] > mx)
mx = cnt[a[x]], now = a[x];
}
void calc(int x) {
solve(x);
for (auto v : e[x])
if (v != f[x])
calc(v);
}
void dsu(int x) {
for (auto v : e[x])
if (v != f[x] && v != son[x])
dsu(v), clear(v);
if (son[x])
dsu(son[x]);
for (auto v : e[x])
if (v != f[x] && v != son[x])
calc(v);
solve(x);
ans[x] = now;
}
signed main() {
openfile();
n = read();
for (int i = 1; i <= n; i++)
a[i] = read();
for (int i = 1; i < n; i++) {
int x = read(), y = read();
e[x].push_back(y), e[y].push_back(x);
}
dfs(1, 0);
dsu(1);
for (int i = 1; i <= n; i++)
printf("%lld ", ans[i]);
cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
return 0;
}
虚树(消耗战)
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e6 + 10;
int n, m;
int head[maxn], tot;
int dfn[maxn], top[maxn], dep[maxn], siz[maxn], fa[maxn], son[maxn], cnt;
int a[maxn], k, f[maxn];
int sta[maxn], ding;
vector<int> v[maxn];
struct node {
int y, z, nex;
} e[maxn];
void dfs1(int x, int _fa) {
siz[x] = 1;
fa[x] = _fa;
dep[x] = dep[_fa] + 1;
int maxx = 0;
for (int i = head[x]; i; i = e[i].nex) {
int v = e[i].y;
if (v == _fa)
continue;
f[v] = min(f[x], e[i].z);
dfs1(v, x);
siz[x] += siz[v];
if (siz[v] > maxx)
maxx = siz[v], son[x] = v;
}
}
void dfs2(int u, int fr) {
top[u] = fr, dfn[u] = ++cnt;
if (!son[u])
return;
dfs2(son[u], fr);
for (int i = head[u]; i; i = e[i].nex) {
int v = e[i].y;
if (v != fa[u] && v != son[u])
dfs2(v, v);
}
}
int lca(int a, int b) {
while (top[a] != top[b])
dep[top[a]] > dep[top[b]] ? a = fa[top[a]] : b = fa[top[b]];
return dep[a] < dep[b] ? a : b;
}
void add(int x, int y, int z) {
e[++tot] = {y, z, head[x]};
head[x] = tot;
}
bool cmp(int x, int y) {
return dfn[x] < dfn[y];
}
void add(int x) {
if (ding == 1) {
sta[++ding] = x;
return;
}
int l = lca(x, sta[ding]);
if (l == sta[ding])
return;
while (ding > 1 && dfn[sta[ding - 1]] >= dfn[l])
v[sta[ding - 1]].push_back(sta[ding]), --ding;
if (sta[ding] != l)
v[l].push_back(sta[ding]), sta[ding] = l;
sta[++ding] = x;
}
int dp(int u) {
if (v[u].size() == 0)
return f[u];
int temp = 0;
for (int i = 0; i < v[u].size(); ++i)
temp += dp(v[u][i]);
v[u].clear();
return min(f[u], temp);
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin >> n;
for (int i = 1; i < n; i++) {
int x, y, z;
cin >> x >> y >> z;
add(x, y, z);
add(y, x, z);
}
f[1] = 0x3f3f3f3f3f3f3f3f;
dfs1(1, 0), dfs2(1, 1);
cin >> m;
while (m--) {
cin >> k;
for (int i = 1; i <= k; ++i)
cin >> a[i];
sort(a + 1, a + k + 1, cmp);
sta[ding = 1] = 1;
for (int i = 1; i <= k; ++i)
add(a[i]);
while (ding)
v[sta[ding - 1]].push_back(sta[ding]), --ding;
cout << dp(1) << endl;
}
return 0;
}
点分治1
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
#define mp make_pair
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const ll inf = 0x3f3f3f3f3f3f3f3f;
namespace IO {
void openfile() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
}
int mul(int x, int y) {
return 1ll * x * y % mod;
}
int add(ll x, ll y) {
x += y;
if (x >= mod)
x -= mod;
return x;
}
int sub(int x, int y) {
return add(x, mod - y);
}
inline int read() {
int x = 0, f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
return x;
}
} // namespace IO
using namespace IO;
int n, m, wen[maxn], ans[maxn];
int b[maxn], d[maxn], root, vis[maxn];
int siz[maxn], mx[maxn], t[maxn], cnt, col[maxn];
vector<pii> e[maxn];
void getroot(int x, int fa, int tot) {
siz[x] = 1;
mx[x] = 0;
for (auto vv : e[x]) {
int v = vv.first;
if (v == fa || vis[v])
continue;
getroot(v, x, tot);
siz[x] += siz[v];
mx[x] = max(mx[x], siz[v]);
}
mx[x] = max(mx[x], tot - siz[x]);
if (mx[x] < mx[root] || !root)
root = x;
}
void getdis(int x, int fa, int dis, int color) {
t[++cnt] = x;
d[x] = dis;
col[x] = color;
for (auto vv : e[x]) {
int v = vv.first, z = vv.second;
if (v == fa || vis[v])
continue;
getdis(v, x, dis + z, color);
}
}
bool cmp(int x, int y) {
return d[x] < d[y];
}
void calc(int x) {
cnt = 1;
t[cnt] = x;
d[x] = 0;
col[x] = x;
for (auto vv : e[x]) {
int v = vv.first, z = vv.second;
if (vis[v])
continue;
getdis(v, x, z, v);
}
sort(t + 1, t + 1 + cnt, cmp);
for (int i = 1; i <= m; i++) {
int l = 1, r = cnt;
if (ans[i])
continue;
while (l < r) {
if (d[t[l]] + d[t[r]] > wen[i])
r--;
else if (d[t[l]] + d[t[r]] < wen[i])
l++;
else if (col[t[l]] == col[t[r]])
if (d[t[l]] == d[t[l + 1]])
l++;
else
r--;
else {
ans[i] = 1;
break;
}
}
}
}
void solve(int x) {
vis[x] = 1;
calc(x);
for (auto vv : e[x]) {
int v = vv.first;
if (vis[v])
continue;
root = 0;
getroot(v, 0, siz[v]);
getroot(root, 0, siz[v]);
solve(root);
}
}
signed main() {
openfile();
n = read(), m = read();
for (int i = 1; i < n; i++) {
int x = read(), y = read(), z = read();
e[x].push_back(mp(y, z));
e[y].push_back(mp(x, z));
}
for (int i = 1; i <= m; i++)
wen[i] = read();
getroot(1, 0, n);
solve(root);
for (int i = 1; i <= m; i++)
if (ans[i])
puts("AYE");
else
puts("NAY");
cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n';
return 0;
}
动态点分治(捉迷藏)
#include <bits/stdc++.h>
using namespace std;
#define void inline void
#define int long long
const int maxn = 1e5 + 10;
int n;
int ques;
int now[maxn], d[maxn];
int mx[maxn], siz[maxn], f[maxn][31], root;
int par[maxn];
bool vis[maxn];
int num;
namespace IO
{
template <typename T>
void read(T &x)
{
x = 0;
bool f = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
if (f)
x = -x;
}
template <typename T, typename... Args>
void read(T &x, Args &...args) { read(x), read(args...); }
template <typename T>
void write(T x)
{
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar('0' + x % 10);
}
}
using namespace IO;
struct que
{
priority_queue<int> x, y;
void push(int a) { x.push(a); }
void del(int a) { y.push(a); }
int top()
{
while (y.size() && x.top() == y.top())
x.pop(), y.pop();
return x.top();
}
int size() { return x.size() - y.size(); }
void pop()
{
while (y.size() && x.top() == y.top())
x.pop(), y.pop();
x.pop();
}
int sectop()
{
int a = top();
pop();
int b = top();
push(a);
return b;
}
} q, q1[maxn], q2[maxn];
struct node
{
int y, nex;
} e[maxn * 2];
int head[maxn], tot;
void add(int x, int y)
{
e[++tot] = {y, head[x]};
head[x] = tot;
}
void dfs(int x, int fa)
{
d[x] = d[fa] + 1;
siz[x] = 1;
f[x][0] = fa;
for (int i = 1; i <= 20; i++)
f[x][i] = f[f[x][i - 1]][i - 1];
for (int i = head[x]; i; i = e[i].nex)
{
int v = e[i].y;
if (v == fa)
continue;
dfs(v, x);
siz[x] += siz[v];
}
return;
}
int lca(int x, int y)
{
if (x == y)
return x;
if (d[x] > d[y])
swap(x, y);
for (int i = 20; i >= 0; i--)
if (d[f[y][i]] >= d[x])
y = f[y][i];
if (x == y)
return x;
for (int i = 20; i >= 0; i--)
if (f[x][i] != f[y][i])
x = f[x][i], y = f[y][i];
return f[x][0];
}
int dis(int x, int y)
{
return d[x] + d[y] - 2 * d[lca(x, y)];
}
void getroot(int x, int fa, int size_)
{
siz[x] = 1;
mx[x] = 0;
for (int i = head[x]; i; i = e[i].nex)
{
int v = e[i].y;
if (vis[v] || v == fa)
continue;
getroot(v, x, size_);
siz[x] += siz[v];
mx[x] = max(mx[x], siz[v]);
}
mx[x] = max(mx[x], size_ - siz[x]);
if (!root || mx[root] > mx[x])
root = x;
}
void calc(int x, int fa)
{
q2[root].push(dis(x, par[root]));
siz[x] = 1;
for (int i = head[x]; i; i = e[i].nex)
{
int v = e[i].y;
if (vis[v] || v == fa)
continue;
calc(v, x);
siz[x] += siz[v];
}
return;
}
void Del(int x)
{
if (q1[x].size() >= 2)
q.del(q1[x].top() + q1[x].sectop());
}
void Ins(int x)
{
if (q1[x].size() >= 2)
q.push(q1[x].top() + q1[x].sectop());
}
void build(int x, int fa)
{
vis[x] = 1, q1[x].push(0);
par[x] = fa;
calc(x, 0);
for (int i = head[x]; i; i = e[i].nex)
{
int v = e[i].y;
if (vis[v])
continue;
root = 0;
getroot(v, 0, siz[v]);
build(v = root, x);
q1[x].push(q2[v].top());
}
return Ins(x);
}
void change(int x)
{
if (!now[x])
{
num--, Del(x), q1[x].del(0), Ins(x);
for (int i = x; par[i]; i = par[i])
{
Del(par[i]);
q1[par[i]].del(q2[i].top());
q2[i].del(dis(x, par[i]));
if (q2[i].size())
q1[par[i]].push(q2[i].top());
Ins(par[i]);
}
}
else
{
num++, Del(x), q1[x].push(0), Ins(x);
for (int i = x; par[i]; i = par[i])
{
Del(par[i]);
if (q2[i].size())
q1[par[i]].del(q2[i].top());
q2[i].push(dis(x, par[i]));
q1[par[i]].push(q2[i].top());
Ins(par[i]);
}
}
now[x] ^= 1;
return;
}
int ask()
{
if (num < 2)
return num - 1;
return q.top();
}
signed main()
{
read(n);
num = n;
for (int i = 1; i < n; i++)
{
int x, y;
read(x, y);
add(x, y);
add(y, x);
}
dfs(1, 0);
getroot(1, 0, n);
build(root, 0);
read(ques);
while (ques--)
{
char op;
int x;
scanf("%s", &op);
if (op == 'C')
{
read(x);
change(x);
}
else
write(ask()), putchar('\n');
}
return 0;
}
哈希表
constexpr int SIZE = 1000000;
constexpr int M = 999997;
struct HashTable {
struct Node {
int next, value, key;
} data[SIZE];
int head[M], size;
int f(int key) { return (key % M + M) % M; }
int get(int key) {
for (int p = head[f(key)]; p; p = data[p].next)
if (data[p].key == key) return data[p].value;
return -1;
}
int modify(int key, int value) {
for (int p = head[f(key)]; p; p = data[p].next)
if (data[p].key == key) return data[p].value = value;
}
int add(int key, int value) {
if (get(key) != -1) return -1;
data[++size] = Node{head[f(key)], value, key};
head[f(key)] = size;
return value;
}
};
struct hash_map { // 哈希表模板
struct data {
long long u;
int v, nex;
}; // 前向星结构
data e[SZ << 1]; // SZ 是 const int 表示大小
int h[SZ], cnt;
int hash(long long u) { return (u % SZ + SZ) % SZ; }
// 这里使用 (u % SZ + SZ) % SZ 而非 u % SZ 的原因是
// C++ 中的 % 运算无法将负数转为正数
int& operator[](long long u) {
int hu = hash(u); // 获取头指针
for (int i = h[hu]; i; i = e[i].nex)
if (e[i].u == u) return e[i].v;
return e[++cnt] = data{u, -1, h[hu]}, h[hu] = cnt, e[cnt].v;
}
hash_map() {
cnt = 0;
memset(h, 0, sizeof(h));
}
};