首页 > 其他分享 >线段树优化建图

线段树优化建图

时间:2024-07-21 12:17:50浏览次数:12  
标签:int 线段 back 建图 push dis 优化 id op

首先看这个问题:

一张 \(N\) 个点的有向图,初始没有任何边,有 \(M\) 次操作:

  • 建 \(1\) 条边 \(u\rightarrow v\),边权为 \(w\)。
  • 建 \(r-l+1\) 条边 \(u\rightarrow \forall i\in[l,r]\),边权为 \(w\)。
  • 建 \(r-l+1\) 条边 \(\forall i\in[l,r]\rightarrow u\),边权为 \(w\)。

求建完边后从 \(1\) 到所有点的最短路。

直接暴力建边肯定是无法接受的,所以我们使用线段树的思想试一试,先建一棵线段树,但这棵树是外向的:

image

这时可以发现,所有询问的区间均可拆成 \(O(\log N)\) 个区间!这样就能大大降低时间和空间复杂度。

但这只能解决第 \(2\) 种类型的边,所以还需要建一棵内向的线段树,并把边权设为 \(0\):

image

时间复杂度 \(O(M\log N)\),空间复杂度 \(O(N+M\log N)\)。

代码

#include<bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
using ll = long long;

const int MAXN = 100001;
const ll INF = (ll)(1e18);

struct Node {
  int u;
  ll dis;
};

struct cmp {
  bool operator()(const Node &a, const Node &b) const {
    return a.dis > b.dis;
  }
};

vector<pii> e[10 * MAXN];

struct Segment_Tree {
  int l[4 * MAXN], r[4 * MAXN], id[4 * MAXN];
  void build(int u, int s, int t, int x, bool op) {
    l[u] = s, r[u] = t, id[u] = u + x;
    if(s == t) {
      (!op ? e[id[u]].push_back({s, 0}) : e[s].push_back({id[u], 0}));
      return;
    }
    int mid = (s + t) >> 1;
    build(2 * u, s, mid, x, op), build(2 * u + 1, mid + 1, t, x, op);
    (!op ? (e[id[u]].push_back({id[2 * u], 0}), e[id[u]].push_back({id[2 * u + 1], 0})) : (e[id[2 * u]].push_back({id[u], 0}), e[id[2 * u + 1]].push_back({id[u], 0})));
  }
  void update(int u, int s, int t, int v, int w, bool op) {
    if(l[u] >= s && r[u] <= t) {
      (!op ? e[v].push_back({id[u], w}) : e[id[u]].push_back({v, w}));
      return;
    }
    if(s <= r[2 * u]) {
      update(2 * u, s, t, v, w, op);
    }
    if(t >= l[2 * u + 1]) {
      update(2 * u + 1, s, t, v, w, op);
    }
  }
}tr[2];

int n, q, s;
bool vis[10 * MAXN];
ll dist[10 * MAXN];

void dij(int s) {
  priority_queue<Node, vector<Node>, cmp> pq;
  fill(dist + 1, dist + 10 * n + 1, INF);
  dist[s] = 0;
  pq.push({s, 0});
  for(; !pq.empty(); ) {
    auto [u, dis] = pq.top();
    pq.pop();
    if(vis[u]) {
      continue;
    }
    vis[u] = 1;
    for(auto [v, w] : e[u]) {
      if(dis + w < dist[v]) {
        dist[v] = dis + w;
        pq.push({v, dis + w});
      }
    }
  }
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n >> q >> s;
  tr[0].build(1, 1, n, n, 0), tr[1].build(1, 1, n, 5 * n, 1);
  for(int i = 1, op, u, v, w, l, r; i <= q; ++i) {
    cin >> op;
    if(op == 1) {
      cin >> u >> v >> w;
      e[u].push_back({v, w});
    }else if(op == 2) {
      cin >> u >> l >> r >> w;
      tr[0].update(1, l, r, u, w, 0);
    }else {
      cin >> u >> l >> r >> w;
      tr[1].update(1, l, r, u, w, 1);
    }
  }
  dij(s);
  for(int i = 1; i <= n; ++i) {
    cout << (dist[i] == INF ? -1 : dist[i]) << " ";
  }
  return 0;
}

标签:int,线段,back,建图,push,dis,优化,id,op
From: https://www.cnblogs.com/yaosicheng124/p/18314339

相关文章

  • 【故障诊断】基于斑马优化算法ZOA优化长短记忆网络LSTM实现故障诊断附matlab代码
    %导入数据集load(‘fault_diagnosis_data.mat’);%假设故障诊断数据保存在fault_diagnosis_data.mat文件中%数据预处理%这里省略了数据预处理的步骤,包括数据归一化、特征提取等%划分训练集和测试集train_ratio=0.8;%训练集占总数据的比例train_size=round......
  • 【独家首发】Matlab实现淘金优化算法GRO优化Transformer-LSTM实现负荷数据回归预测
    %导入数据集load(‘load_data.mat’);%假设负荷数据保存在load_data.mat文件中%数据预处理%这里省略了数据预处理的步骤,包括数据归一化、特征提取等%构建Transformer-LSTM模型model=create_transformer_lstm_model();%自定义创建Transformer-LSTM模型的函数......
  • 【独家首发】Matlab实现狮群优化算法LSO优化Transformer-LSTM实现负荷数据回归预测
    %导入数据集load(‘load_data.mat’);%假设负荷数据保存在load_data.mat文件中%数据预处理%这里省略了数据预处理的步骤,包括数据归一化、特征提取等%构建Transformer-LSTM模型model=create_transformer_lstm_model();%自定义创建Transformer-LSTM模型的函数......
  • 让 cpython 优化恒定条件
    我正在用Python编写需要尽可能高效运行的代码,但有时我需要深入挖掘调试语句。不要注释这些输入或输出(或者使用外部预处理器来处理代码,就像这里建议的那样Python相当于#ifdefDEBUG或这里如何在python中实现“#ifdef”?|||)我想在模块的开头定义一个变量......
  • SQL Server性能优化秘籍:自定义统计信息收集的艺术
    SQLServer性能优化秘籍:自定义统计信息收集的艺术在数据库管理中,统计信息是优化查询性能的关键。SQLServer通过自动收集统计信息来帮助查询优化器选择最佳的执行计划。然而,在某些情况下,自动收集可能不足以满足特定需求。本文将详细介绍如何在SQLServer中实现数据库的自定......
  • G2O(3) 基本例子 2D-3D位姿优化
        #include<iostream>#include<opencv2/core/core.hpp>#include<opencv2/features2d/features2d.hpp>#include<opencv2/highgui/highgui.hpp>#include<opencv2/calib3d/calib3d.hpp>#include<Eigen/Core>#include&l......
  • 【学习笔记】线段树优化建图
    前言2023.5.31贺了线段树优化建图板子。当时那段时间还被\(bobo\)一顿乱\(D\),让我多写点\(DP\),数学,少些点重复的数据结构。2024.7.19没想到暑假集训CSP提高模拟2\(T3\)放了个线段树优化建图板子,加上之前线段树优化建图代码是贺的,今年寒假本想找时间步一下的结果没去......
  • debian系统优化
    第一,安装vim在Debian系统中安装Vim可以通过APT包管理器来完成。打开终端,然后执行以下命令:更新APT包索引:sudoaptupdate安装Vim:sudoaptinstallvim这将会安装Vim文本编辑器。安装完成后,你可以通过在终端中输入vim来启动Vim。 第二,开启root登录 ......
  • 干货| Python代码性能优化总结
    本文会介绍不少的Python代码加速运行的技巧。在深入代码优化细节之前,需要了解一些代码优化基本原则。第一个基本原则:不要过早优化很多人一开始写代码就奔着性能优化的目标,“让正确的程序更快要比让快速的程序正确容易得多”。因此,优化的前提是代码能正常工作。过早地进......
  • 线段树
    把给定的区间转换成如图所示的一棵二叉树每次把区间一分为2,左边是左儿子,右边是右儿子对于每个节点的信息,都可以由两个儿子的信息得到如何单点查询/修改可以发现,两个儿子处理的区间没有交集,所以每次只要判断是在左儿子还是在右儿子,不断的递归对于区间查询,每一......