- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
在建图连边的过程中,我们时常会碰到这种题目,一个点向一段连续的区间中的点连边或者一个连续的区间向一个点连边,如果我们真的一条一条连过去,那一旦点的数量多了复杂度就爆炸了,这里就需要用线段树的区间性质来优化我们的建图了.
那棵线段树大概长这个样子.
到时候加边的时候是这个样子的。(为了不影响边的显示,只能把点放在这里了) 。
个人感觉,这是一个可以优化的 方法 ,算不上什么很高级的算法或数据结构,题目照常做即可.
Legacy - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 。
模板题,也是自己少数不看题解独立做出来的题目.
线段树上建图 + 最短路.
这里还用了动态开点(因为这个蒟蒻不会用二叉树的性质来建造下面部分的线段树).
//The code was written by yifan, and yifan is neutral!!!
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define bug puts("NOIP rp ++!");
template<typename T>
inline T read() {
T x = 0;
bool fg = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
fg |= (ch == '-');
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return fg ? ~x + 1 : x;
}
using pil = pair<int, ll>;
using pli = pair<ll, int>;
const int N = 1e5 + 5;
int n, q, s, tot, rt1, rt2;
int pos[N];
ll dis[N << 3];
vector<pil> e[N << 3];
bitset<(N << 3)> vis;
struct seg {
int l, r, lson, rson;
} t[N << 3];
inline int ls(int u) {
return t[u].lson;
}
inline int rs(int u) {
return t[u].rson;
}
void build(int &u, int l, int r) {
u = ++ tot;
t[u] = seg{l, r};
if (l == r) {
pos[l] = u;
return ;
}
int mid = (l + r) >> 1;
build(t[u].lson, l, mid);
build(t[u].rson, mid + 1, r);
e[u].emplace_back(ls(u), 0);
e[u].emplace_back(rs(u), 0);
}
void add1(int u, int lr, int rr, int v, ll w) {
if (lr <= t[u].l && t[u].r <= rr) {
e[v].emplace_back(u, w);
return ;
}
int mid = (t[u].l + t[u].r) >> 1;
if (lr <= mid) {
add1(ls(u), lr, rr, v, w);
}
if (rr > mid) {
add1(rs(u), lr, rr, v, w);
}
}
void add2(int u, int lr, int rr, int v, ll w) {
if (lr <= t[u].l && t[u].r <= rr) {
e[u].emplace_back(v, w);
return ;
}
int mid = (t[u].l + t[u].r) >> 1;
if (lr <= mid) {
add2(ls(u), lr, rr, v, w);
}
if (rr > mid) {
add2(rs(u), lr, rr, v, w);
}
}
void dij(int S) {
priority_queue<pli, vector<pli>, greater<pli> > q;
int tot = (n << 2);
for (int i = 1; i <= tot; ++ i) {
dis[i] = 1e18;
}
dis[S] = 0;
q.emplace(dis[S], S);
while (! q.empty()) {
pli fr = q.top();
q.pop();
int u = fr.second;
if (vis[u]) continue ;
for (pil it : e[u]) {
int v = it.first;
ll w = it.second;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
q.emplace(dis[v], v);
}
}
}
}
void build2(int &u, int l, int r) {
if (l == r) {
u = pos[l];
return ;
}
u = ++ tot;
t[u] = seg{l, r};
int mid = (l + r) >> 1;
build2(t[u].lson, l, mid);
build2(t[u].rson, mid + 1, r);
e[ls(u)].emplace_back(u, 0);
e[rs(u)].emplace_back(u, 0);
}
int main() {
n = read<int>(), q = read<int>(), s = read<int>();
build(rt1, 1, n);
build2(rt2, 1, n);
for (int i = 1, op, u; i <= q; ++ i) {
op = read<int>(), u = read<int>();
if (op == 1) {
int v = read<int>();
ll w = read<ll>();
e[pos[u]].emplace_back(pos[v], w);
} else if (op == 2) {
int l = read<int>(), r = read<int>();
ll w = read<ll>();
add1(rt1, l, r, pos[u], w);
} else {
int l = read<int>(), r = read<int>();
ll w = read<ll>();
add2(rt2, l, r, pos[u], w);
}
}
dij(pos[s]);
for (int i = 1; i <= n; ++ i) {
if (dis[pos[i]] == 1e18) {
cout << -1;
} else {
cout << dis[pos[i]];
}
putchar(' ');
}
putchar('\n');
return 0;
}
P5025 [SNOI2017] 炸弹 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 。
这是一道融合了线段树优化建图和 tarjan 缩点的题目,建好图后进行缩点,然后再 dfs 寻找能引爆的最左端点和最右端点.
//The code was written by yifan, and yifan is neutral!!!
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define bug puts("NOIP rp ++!");
template<typename T>
inline T read() {
T x = 0;
bool fg = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
fg |= (ch == '-');
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return fg ? ~x + 1 : x;
}
const int N = 5e5 + 5;
const int mod = 1e9 + 7;
int n, tim, Scc, mx;
int pos[N], dfn[N << 2], low[N << 2], scc[N << 2];
int le[N << 2], re[N << 2];
ll x[N], r[N];
vector<int> e[N << 2], st, ne[N << 2];
bitset<(N << 2)> vis;
struct seg {
int l, r;
} t[N << 2];
inline int ls(int u) {
return (u << 1);
}
inline int rs(int u) {
return (u << 1 | 1);
}
void build(int u, int l, int r) {
t[u] = seg{l, r};
mx = max(mx, u);
if (l == r) {
pos[l] = u;
return ;
}
int mid = (l + r) >> 1;
build(ls(u), l, mid);
build(rs(u), mid + 1, r);
e[u].emplace_back(ls(u));
e[u].emplace_back(rs(u));
}
void connect(int u, int l, int r, int lr, int rr, int v) {
if (lr <= l && r <= rr) {
if (v == u) return ;
e[v].emplace_back(u);
return ;
}
int mid = (l + r) >> 1;
if (lr <= mid) {
connect(ls(u), l, mid, lr, rr, v);
}
if (rr > mid) {
connect(rs(u), mid + 1, r, lr, rr, v);
}
}
void tarjan(int u) {
dfn[u] = low[u] = ++ tim;
st.emplace_back(u);
for (int v : e[u]) {
if (! dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if (! scc[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
scc[u] = ++ Scc;
le[Scc] = min(t[u].l, le[Scc]);
re[Scc] = max(t[u].r, re[Scc]);
while (st.back() != u) {
scc[st.back()] = Scc;
le[Scc] = min(t[st.back()].l, le[Scc]);
re[Scc] = max(t[st.back()].r, re[Scc]);
st.pop_back();
}
st.pop_back();
}
}
void dfs(int u) {
vis.set(u);
for (int v : ne[u]) {
if (vis[v]) {
le[u] = min(le[u], le[v]);
re[u] = max(re[u], re[v]);
continue ;
}
dfs(v);
le[u] = min(le[u], le[v]);
re[u] = max(re[u], re[v]);
}
}
int main() {
n = read<int>();
for (int i = 1; i <= n; ++ i) {
x[i] = read<ll>(), r[i] = read<ll>();
}
memset(le, 127, sizeof le);
build(1, 1, n);
for (int i = 1, L, R; i <= n; ++ i) {
if (!r[i]) continue ;
L = lower_bound(x + 1, x + n + 1, x[i] - r[i]) - x;
R = upper_bound(x + 1, x + n + 1, x[i] + r[i]) - x - 1;
connect(1, 1, n, L, R, pos[i]);
t[pos[i]] = seg{L, R};
}
for (int i = 1; i <= n; ++ i) {
if (! dfn[i]) {
tarjan(i);
}
}
for (int i = 1; i <= mx; ++ i) {
for (int u : e[i]) {
if (scc[u] == scc[i]) continue ;
ne[scc[i]].emplace_back(scc[u]);
}
}
for (int i = 1; i <= Scc; ++ i) {
sort(ne[i].begin(), ne[i].end());
ne[i].erase(unique(ne[i].begin(), ne[i].end()), ne[i].end());
}
for (int i = 1; i <= Scc; ++ i) {
if (! vis[i]) {
dfs(i);
}
}
ll ans = 0;
for (int i = 1; i <= n; ++ i) {
ans = (ans + (1ll * (1ll * re[scc[pos[i]]] - le[scc[pos[i]]] + 1) * i) % mod) % mod;
}
cout << ans;
putchar('\n');
return 0;
}
最后此篇关于「学习笔记」线段树优化建图的文章就讲到这里了,如果你想了解更多关于「学习笔记」线段树优化建图的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
关于 B 树与 B+ 树,网上有一个比较经典的问题:为什么 MongoDb 使用 B 树,而 MySQL 索引使用 B+ 树? 但实际上 MongoDb 真的用的是 B 树吗?
如何将 R* Tree 实现为持久(基于磁盘)树?保存 R* 树索引或保存叶值的文件的体系结构是什么? 注意:此外,如何在这种持久性 R* 树中执行插入、更新和删除操作? 注意事项二:我已经实现了一个
目前,我正在努力用 Java 表示我用 SML 编写的 AST 树,这样我就可以随时用 Java 遍历它。 我想知道是否应该在 Java 中创建一个 Node 类,其中包含我想要表示的数据,以及一个数
我之前用过这个库http://www.cs.umd.edu/~mount/ANN/ .但是,它们不提供范围查询实现。我猜是否有一个 C++ 范围查询实现(圆形或矩形),用于查询二维数据。 谢谢。 最佳
在进一步分析为什么MySQL数据库索引选择使用B+树之前,我相信很多小伙伴对数据结构中的树还是有些许模糊的,因此我们由浅入深一步步探讨树的演进过程,在一步步引出B树以及为什么MySQL数据库索引选择
书接上回,今天和大家一起动手来自己实现树。 相信通过前面的章节学习,大家已经明白树是什么了,今天我们主要针对二叉树,分别使用顺序存储和链式存储来实现树。 01、数组实现 我们在上一节中说过,
书节上回,我们接着聊二叉树,N叉树,以及树的存储。 01、满二叉树 如果一个二叉树,除最后一层节点外,每一层的节点数都达到最大值,即每个节点都有两个子节点,同时所有叶子节点都在最后一层,则这个
树是一种非线性数据结构,是以分支关系定义的层次结构,因此形态上和自然界中的倒挂的树很像,而数据结构中树根向上树叶向下。 什么是树? 01、定义 树是由n(n>=0)个元素节点组成的
操作系统的那棵“树” 今天从一颗 开始,我们看看如何从小树苗长成一颗苍天大树。 运转CPU CPU运转起来很简单,就是不断的从内存取值执行。 CPU没有好好运转 IO是个耗费时间的活,如果CPU在取值
我想为海洋生物学类(class)制作一个简单的系统发育树作为教育示例。我有一个具有分类等级的物种列表: Group <- c("Benthos","Benthos","Benthos","Be
我从这段代码中删除节点时遇到问题,如果我插入数字 12 并尝试删除它,它不会删除它,我尝试调试,似乎当它尝试删除时,它出错了树的。但是,如果我尝试删除它已经插入主节点的节点,它将删除它,或者我插入数字
B+ 树的叶节点链接在一起。将 B+ 树的指针结构视为有向图,它不是循环的。但是忽略指针的方向并将其视为链接在一起的无向叶节点会在图中创建循环。 在 Haskell 中,如何将叶子构造为父内部节点的子
我在 GWT 中使用树控件。我有一个自定义小部件,我将其添加为 TreeItem: Tree testTree = new Tree(); testTree.addItem(myWidget); 我想
它有点像混合树/链表结构。这是我定义结构的方式 struct node { nodeP sibling; nodeP child; nodeP parent; char
我编写了使用队列遍历树的代码,但是下面的出队函数生成错误,head = p->next 是否有问题?我不明白为什么这部分是错误的。 void Levelorder(void) { node *tmp,
例如,我想解析以下数组: var array1 = ["a.b.c.d", "a.e.f.g", "a.h", "a.i.j", "a.b.k"] 进入: var json1 = { "nod
问题 -> 给定一棵二叉树和一个和,确定该树是否具有从根到叶的路径,使得沿路径的所有值相加等于给定的和。 我的解决方案 -> public class Solution { public bo
我有一个创建 java 树的任务,它包含三列:运动名称、运动类别中的运动计数和上次更新。类似的东西显示在下面的图像上: 如您所见,有 4 种运动:水上运动、球类运动、跳伞运动和舞蹈运动。当我展开 sk
我想在 H2 数据库中实现 B+ Tree,但我想知道,B+ Tree 功能在 H2 数据库中可用吗? 最佳答案 H2 已经使用了 B+ 树(PageBtree 类)。 关于mysql - H2数据库
假设我们有 5 个字符串数组: String[] array1 = {"hello", "i", "cat"}; String[] array2 = {"hello", "i", "am"}; Str
我是一名优秀的程序员,十分优秀!