• CF786B Legacy


    好久没有看到这样让人惊叹的建图方法了, 需要记录一下这个线段树优化建图的思路.
    这位大佬 讲的已经很好了, 看他的就行.
    其实这一题本质上就是用增加 (logN) 级别的点的代价将 (O(N^2)) 时间的建边优化到 (O(NlogN)) , 的确是线段树的思想.
    开两颗线段树是防止冲突. 的确很妙.

    #include <queue>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <cassert>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef pair<ll, ll> P;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    const int MAXN = 1e5 + 10;
    inline int read(){
        char ch = getchar(); int x = 0;
        while(!isdigit(ch)) ch = getchar();
        while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
        return x;
    }
    
    int N, Q, S;
    
    struct edge
    {
        int to, cost;
    };vector<edge> g[MAXN << 2];
    
    namespace stree
    {
        #define mid ((l + r) >> 1)
    
        struct Node
        {
            int ls, rs;
        }node[MAXN << 2];
        int rootin, rootout;
    
        int pos;
    
        void build(int &o, int l, int r, bool Type) {
            if(l == r) return o = l, void();
            o = ++pos;
            build(node[o].ls, l, mid, Type),
            build(node[o].rs, mid + 1, r, Type);
            if(Type) {
                g[o].push_back((edge) {node[o].ls, 0}),
                g[o].push_back((edge) {node[o].rs, 0});
            }
            else {
                g[node[o].ls].push_back((edge) {o, 0});
                g[node[o].rs].push_back((edge) {o, 0});
            }
        }
    
        void modify(int &o, int l, int r, int a, int b, int u, int c, bool Type) {
            if(l > b || r < a) return ;
            if(a <= l && r <= b) {
                if(Type) g[u].push_back((edge) {o, c});
                else g[o].push_back((edge) {u, c});
                return;
            }
            modify(node[o].ls, l, mid, a, b, u, c, Type);
            modify(node[o].rs, mid + 1, r, a, b, u, c, Type);
        }
        #undef mid
    }
    
    inline bool tension(const ll st, ll &lg) {
        return lg > st ? (lg = st, true) : false;
    }
    
    ll dis[MAXN << 2];
    void dijkstra() {
        priority_queue<P, vector<P>, greater<P> > q;
        memset(dis, 0x3f, sizeof(dis));
        dis[S] = 0, q.push(P(0, S));
    
        while(!q.empty()) {
            P p = q.top(); q.pop();
            int u = p.second;
            if(dis[u] < p.first) continue;
    
            for(int i = 0; i < (int) g[u].size(); i++) {
                edge &e = g[u][i];
                if(tension(dis[u] + e.cost, dis[e.to]))
                    q.push(P(dis[e.to], e.to));
            }
        }
    }
    
    int main(){
        cin>>N>>Q>>S;
        using namespace stree;
        pos = N; build(rootin, 1, N, true), build(rootout, 1, N, false);
        while(Q--) {
            int opt = read();
            if(opt == 1) {
                int u = read(), v = read(), c = read();
                g[u].push_back((edge) {v, c});
            }
            else if(opt == 2) {
                int u = read(), l = read(), r = read(), c = read();
                modify(rootin, 1, N, l, r, u, c, true);
            }
            else {
                int u = read(), l = read(), r = read(), c = read();
                modify(rootout, 1, N, l, r, u, c, false);
            }
        }
        dijkstra();
        for(int i = 1; i <= N; i++) 
            cout<<(dis[i] == INF ? -1 : dis[i])<<" ";
        return 0;
    }
    
    
  • 相关阅读:
    FLEX监视浏览器关闭事件
    [FMS]FMS流媒体服务器onStatus介绍说明
    JS调用水晶报表打印翻页按钮事件
    js之获取窗口大小和位置信息
    Window对象简介
    Js中的window.parent ,window.top,window.self 详解
    flex4+fms3.5+cs4开发实时音视频直播及点播详解
    VS2010与水晶报表V13的打包集成小结
    最完美解决方案:js弹出窗口关闭当前页面,而不弹出提示框
    使用C#将HTML文本转换为普通文本,去掉所有的Html标记(转)
  • 原文地址:https://www.cnblogs.com/wsmrxc/p/9869303.html
Copyright © 2020-2023  润新知