当前位置: 首页 > news >正文

线段树合并与分解

合并

#include <bits/stdc++.h>
using namespace std;
#define asd(i,a,b) for(int i=a;i<=b;i++)
#define int long long
const int inf = 0x3f3f3f3f, N = 1e5 + 5, Z = 1e5;
int n, m, fa[N], o[N][25], dep[N], tot, root[N], ans[N];
vector<int> g[N];
struct node {int l, r, sum, res;
} t[N * 50];void pushup(int o) {if (t[t[o].l].sum < t[t[o].r].sum) {t[o].res = t[t[o].r].res;t[o].sum = t[t[o].r].sum;}else {t[o].res = t[t[o].l].res;t[o].sum = t[t[o].l].sum;}
}void update(int& o, int l, int r, int pos, int val) {if (!o) o = ++tot;if (l == r) {t[o].sum += val;t[o].res = l;return;}int mid = (l + r) >> 1;if (pos <= mid) update(t[o].l, l, mid, pos, val);else update(t[o].r, mid + 1, r, pos, val);pushup(o);
}void merge(int& x, int y, int l, int r) {if (!x || !y) {x = x ? x : y;return;}if (l == r) {t[x].sum += t[y].sum;if (t[x].sum > 0) t[x].res = l;else t[x].res = 0;return;}int mid = (l + r) >> 1;merge(t[x].l, t[y].l, l, mid);merge(t[x].r, t[y].r, mid + 1, r);pushup(x);
}void init(int x, int pre) {o[x][0] = pre;dep[x] = dep[pre] + 1;for (int i = 1; i <= 20; i++) {o[x][i] = o[o[x][i - 1]][i - 1];}for (int y : g[x]) {if (y == pre) continue;init(y, x);}
}int lca(int x, int y) {if (dep[x] < dep[y]) swap(x, y);for (int i = 20; i >= 0; i--) {if (dep[o[x][i]] >= dep[y]) x = o[x][i];}if (x == y) return x;for (int i = 20; i >= 0; i--) {if (o[x][i] != o[y][i]) {x = o[x][i];y = o[y][i];}}return o[x][0];
}void dfs(int x, int fa) {for (int y : g[x]) {if (y == fa) continue;dfs(y, x);merge(root[x], root[y], 1, Z);}ans[x] = t[root[x]].res;
}signed main() {ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cin >> n >> m;asd(i, 1, n - 1) {int u, v; cin >> u >> v;g[u].push_back(v);g[v].push_back(u);}init(1, 0);asd(i, 1, m) {int a, b, c; cin >> a >> b >> c;int ut = lca(a, b);update(root[a], 1, Z, c, 1);update(root[b], 1, Z, c, 1);update(root[ut], 1, Z, c, -1);update(root[o[ut][0]], 1, Z, c, -1);}dfs(1, 0);asd(i, 1, n) cout << ans[i] << '\n';return 0;
}

分裂

P5494 【模板】线段树分裂

题目描述

给出一个可重集 a a a(编号为 1 1 1),它支持以下操作:

0 p x y:将可重集 p p p 中大于等于 x x x 且小于等于 y y y 的值移动到一个新的可重集中(新可重集编号为从 2 2 2 开始的正整数,是上一次产生的新可重集的编号+1)。

1 p t:将可重集 t t t 中的数放入可重集 p p p,且清空可重集 t t t(数据保证在此后的操作中不会出现可重集 t t t)。

2 p x q:在 p p p 这个可重集中加入 x x x 个数字 q q q

3 p x y:查询可重集 p p p 中大于等于 x x x 且小于等于 y y y 的值的个数。

4 p k:查询在 p p p 这个可重集中第 k k k 小的数,不存在时输出 -1

输入格式

第一行两个整数 n , m n,m n,m,表示可重集中的数在 1 ∼ n 1\sim n 1n 的范围内,有 m m m 个操作。

接下来一行 n n n 个整数,表示 1 ∼ n 1 \sim n 1n 这些数在 a a a 中出现的次数 ( a i ≤ m ) (a_{i} \leq m) (aim)

接下来的 m m m 行每行若干个整数,第一个数为操作的编号 o p t opt opt 0 ≤ o p t ≤ 4 0 \leq opt \leq 4 0opt4),以题目描述为准。

输出格式

依次输出每个查询操作的答案。

#include <bits/stdc++.h>
using namespace std;
#define asd(i,a,b) for(int i=a;i<=b;i++)
#define int long long
constexpr int N = 2e5 + 10;
int n, m, idx = 1, cnt, tot;
int sum[N << 5], ls[N << 5], rs[N << 5], root[N << 2], rub[N << 5];int New() { return cnt ? rub[cnt--] : ++tot; }
void Del(int& p) {ls[p] = rs[p] = sum[p] = 0;rub[++cnt] = p;p = 0;
}void push_up(int p) { sum[p] = sum[ls[p]] + sum[rs[p]]; }void build(int s, int t, int& p) {if (!p) p = New();if (s == t) {cin >> sum[p];return;}int m = (s + t) >> 1;build(s, m, ls[p]);build(m + 1, t, rs[p]);push_up(p);
}void update(int x, int c, int s, int t, int& p) {if (!p) p = New();if (s == t) {sum[p] += c;return;}int m = (s + t) >> 1;if (x <= m) update(x, c, s, m, ls[p]);else update(x, c, m + 1, t, rs[p]);push_up(p);
}int merge(int p, int q, int s, int t) {if (!p || !q) return p | q;if (s == t) {sum[p] += sum[q];Del(q);return p;}int m = (s + t) >> 1;ls[p] = merge(ls[p], ls[q], s, m);rs[p] = merge(rs[p], rs[q], m + 1, t);push_up(p);Del(q);return p;
}void split(int& p, int& q, int s, int t, int l, int r) {if (t < l || r < s) return;if (!p) return;if (l <= s && t <= r) {q = p;p = 0;return;}if (!q) q = New();int m = (s + t) >> 1;if (l <= m) split(ls[p], ls[q], s, m, l, r);if (m < r) split(rs[p], rs[q], m + 1, t, l, r);push_up(p);push_up(q);
}int query(int l, int r, int s, int t, int p) {if (!p) return 0;if (l <= s && t <= r) return sum[p];int m = (s + t) >> 1;int ans = 0;if (l <= m) ans += query(l, r, s, m, ls[p]);if (m < r) ans += query(l, r, m + 1, t, rs[p]);return ans;
}int kth(int s, int t, int k, int p) {if (s == t) return s;int m = (s + t) >> 1;int left = sum[ls[p]];if (k <= left) return kth(s, m, k, ls[p]);else return kth(m + 1, t, k - left, rs[p]);
}signed main() {ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cin >> n >> m;build(1, n, root[1]);while (m--) {int op, p, x, y, q, k;cin >> op;switch (op) {case 0:cin >> p >> x >> y;split(root[p], root[++idx], 1, n, x, y);break;case 1:cin >> p >> q;root[p] = merge(root[p], root[q], 1, n);break;case 2:cin >> p >> x >> q;update(q, x, 1, n, root[p]);break;case 3:cin >> p >> x >> y;cout << query(x, y, 1, n, root[p]) << '\n';break;case 4:cin >> p >> k;if (sum[root[p]] < k) cout << "-1\n";else cout << kth(1, n, k, root[p]) << '\n';break;}}return 0;
}

相关文章:

  • 从外卖大战看O2O新趋势:上门私厨平台系统架构设计解析
  • power bi获取局域网内共享文件
  • Kubernetes》》k8s》》Taint 污点、Toleration容忍度
  • dummy cli-tool ubuntu22.04使用
  • QT:自定义ComboBox
  • MySQL 表的约束(二)
  • vs2022解决 此项目需要MFC库。从visual studio安装程序(单个组件选项卡)为正在使用的任何工具和体系结构安装他们问题
  • 【AI生产力工具】Windsurf,一款AI编程工具
  • 目标检测YOLO实战应用案例100讲- 无人机平台下露天目标检测与计数
  • 新能源汽车声纹监测技术的发展趋势是什么?
  • [Linux运维] [Ubuntu/Debian]在Lightsail Ubuntu服务器上安装Python环境的完整指南
  • ETL架构、数据建模及性能优化实践
  • 开源模型应用落地-全能音频新纪元-Kimi-Audio-7B-Instruct-重塑多模态交互边界
  • 网络原理 - 10(HTTP/HTTPS - 1)
  • LBS服务(基于位置的服务)与LLM(大型语言模型)交互功能分析
  • 为什么PPT中的视频无法播放?
  • 【Robocorp实战指南】Python驱动的开源RPA框架
  • 分析整体文档集合质量:来源多样性、内容新鲜度、信息密度、内容具体性
  • JVM——引入
  • 了解Android studio 初学者零基础推荐(1)
  • 特朗普要征100%关税,好莱坞这批境外摄制新片能躲过吗?
  • 医生李某某饮酒上班?重庆长寿区人民医院:正在调查,将严肃处理
  • 世锦赛决赛今夜打响,斯诺克运动需要赵心童创造历史
  • 日本来信|劳动者的书信④
  • 陈燮阳从艺60周年:指挥棒不停,心跳就不会老去
  • 3:0战胜日本队,中国羽毛球队挺进2025苏迪曼杯决赛