【CF786B】Legacy

题目大意:初始给定 N 个点,支持三种操作:两点之间连边;一个点与一个连续区间编号的点之间连边;一个连续区间内的点和一个点连边,求执行 N 次操作之后的单源最短路。

题解:学会了线段树优化建图。
发现若暴力进行连边,时间和空间都会被卡到 \(O(n^2)\),直接起飞。
发现连边的点的编号是连续的,结合线段树可以维护连续区间信息的思想,就产生了线段树优化建图的方法。
在初始的 N 个节点的基础上建立两棵线段树,分别表示入树和出树,其中入树的上的各个节点允许单个节点的连接;出树上的节点允许连接单个节点。对于入树中的每个节点来说,需要连一条边权为 0 的有向边到它的两个儿子,表示若有节点连向父节点,那么一定也连向了儿子节点;对于出树上的每个节点来说,需要连一条边权为 0 的有向边到它的父节点,表示若当前节点可以连向某个节点,那么其子节点也一定可以走到这个节点。
时空复杂度分析:空间为两棵线段树的空间减去一份叶子节点的大小,即:\(3 * n\),时间复杂度为 \(elog^2v\),其中 e 是边的条数,v 是节点的个数。

代码如下

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

struct edge {
    int to;
    LL w;
    edge(int x = -1, int y = -1) {
        to = x, w = y;
    }
};

struct segtree {
    #define ls(o) tree[o].lc
    #define rs(o) tree[o].rc
    struct node {
        int lc, rc;
    };
    vector<node> tree;
    int tot, rootin, rootout;
    segtree(int n, vector<vector<edge>> &adj) {
        tot = n;
        tree.resize(3 * n);
        buildin(rootin, 1, n, adj);
        buildout(rootout, 1, n, adj);
    }
    void buildin(int &o, int l, int r, vector<vector<edge>> &adj) {
        if (l == r) {
            o = l;
            return;
        }
        o = ++tot;
        int mid = l + r >> 1;
        buildin(ls(o), l, mid, adj);
        buildin(rs(o), mid + 1, r, adj);
        adj[o].emplace_back(ls(o), 0);
        adj[o].emplace_back(rs(o), 0);
    }
    void buildout(int &o, int l, int r, vector<vector<edge>> &adj) {
        if (l == r) {
            o = l;
            return;
        }
        o = ++tot;
        int mid = l + r >> 1;
        buildout(ls(o), l, mid, adj);
        buildout(rs(o), mid + 1, r, adj);
        adj[ls(o)].emplace_back(o, 0);
        adj[rs(o)].emplace_back(o, 0);
    }
    void link(int o, int l, int r, int x, int y, int u, int w, int opt, vector<vector<edge>> &adj) {// opt 2 -> in  3 -> out
        if (l == x && r == y) {
            opt == 2 ? adj[u].emplace_back(o, w) : adj[o].emplace_back(u, w);
            return;
        }
        int mid = l + r >> 1;
        if (y <= mid) {
            link(ls(o), l, mid, x, y, u, w, opt, adj);
        } else if (x > mid) {
            link(rs(o), mid + 1, r, x, y, u, w, opt, adj);
        } else {
            link(ls(o), l, mid, x, mid, u, w, opt, adj);
            link(rs(o), mid + 1, r, mid + 1, y, u, w, opt, adj);
        }
    }
};

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int n, m, s;
    cin >> n >> m >> s;
    vector<vector<edge>> adj(3 * n);
    segtree t(n, adj);
    while (m--) {
        int opt;
        cin >> opt;
        if (opt == 1) {
            int u, v, w;
            cin >> u >> v >> w;
            adj[u].emplace_back(v, w);
        } else {
            int u, l, r, w;
            cin >> u >> l >> r >> w;
            t.link(opt == 2 ? t.rootin : t.rootout, 1, n, l, r, u, w, opt, adj);
        }
    }
    vector<LL> d(3 * n, 1e18);
    vector<bool> expand(3 * n);
    priority_queue<pair<LL, int>> q;
    auto dijkstra = [&]() {
        d[s] = 0, q.push(make_pair(0, s));
        while (!q.empty()) {
            int u = q.top().second;
            q.pop();
            if (expand[u] == 1) {
                continue;
            }
            expand[u] = 1;
            for (auto e : adj[u]) {
                int v = e.to, w = e.w;
                if (d[v] > d[u] + w) {
                    d[v] = d[u] + w;
                    q.push(make_pair(-d[v], v));
                }
            }
        }
    };
    dijkstra();
    for (int i = 1; i <= n; i++) {
        if (d[i] == 1e18) {
            cout << "-1" << " ";
        } else {
            cout << d[i] << " ";
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/wzj-xhjbk/p/11528900.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Wireshark Legacy是Wireshark的一个版本,它是一个开源的网络协议分析工具,用于捕获和分析网络数据包。Wireshark Legacy可以帮助用户深入了解网络通信过程,识别和解决网络问题。 使用Wireshark Legacy,您可以: - 捕获网络数据包:Wireshark Legacy可以在网络接口上捕获传输的数据包,以便进行后续分析。 - 分析网络流量:Wireshark Legacy提供了强大的过滤和搜索功能,可以根据各种条件过滤和分析网络流量。 - 解码协议:Wireshark Legacy支持多种协议的解码,包括TCP、UDP、HTTP、DNS等,可以将数据包解码为易于理解的格式。 - 进行网络故障排除:Wireshark Legacy可以帮助您识别网络故障的原因,例如延迟、丢包、错误配置等。 - 分析安全问题:Wireshark Legacy可以帮助您检测和分析网络中的安全问题,例如恶意软件、网络攻击等。 对于Wireshark Legacy的使用,您可以按照以下步骤进行操作: 1. 下载和安装:您可以从Wireshark官网的下载页面(https://www.wireshark.org/#download)选择适合您操作系统的版本,并按照安装向导进行安装。 2. 打开Wireshark Legacy:安装完成后,您可以打开Wireshark Legacy应用程序。 3. 选择网络接口:在Wireshark Legacy的界面中,您可以选择要捕获数据包的网络接口。 4. 开始捕获数据包:点击“开始”按钮,Wireshark Legacy将开始捕获网络数据包。 5. 分析数据包:捕获到数据包后,您可以使用Wireshark Legacy的过滤和搜索功能来分析数据包,查找特定的信息或问题。 6. 解码协议:Wireshark Legacy会自动解码捕获到的数据包,并将其显示为易于理解的格式。 7. 导出和保存数据包:如果需要,您可以将捕获到的数据包导出为文件,以便后续分析或共享。 请注意,Wireshark Legacy是Wireshark的旧版本,建议您使用最新版本的Wireshark以获得更好的功能和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值