[Codeforces 787D] Legacy

[题目链接]

          https://codeforces.com/contest/787/problem/D

[算法]

        线段树优化建边 ,  然后用Dijkstra算法求单源最短路

        时间复杂度 : O((N + M)logN)

[代码]

        

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 10;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const ll inf = 1e15;

struct node
{
        int lc , rc;
} a[MAXN * 10];
struct edge
{
        int to , w , nxt;
} e[MAXN << 4];

int tot , cnt , n , q , s;
int head[MAXN * 10] , root[2];
bool visited[MAXN * 10];
ll dist[MAXN * 10];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
inline void addedge(int x , int y , int w)
{
        ++cnt;
        e[cnt] = (edge){y , w , head[x]};
        head[x] = cnt;
}
inline void buildA(int &now , int l , int r)
{
        if (l == r)
        {
                now = l;
                return;
        }        
        now = ++tot;
        int mid = (l + r) >> 1;
        buildA(a[now].lc , l , mid);
        buildA(a[now].rc , mid + 1 , r);
        addedge(now , a[now].lc , 0);
        addedge(now , a[now].rc , 0);
}
inline void buildB(int &now , int l , int r)
{
        if (l == r)
        {
                now = l;
                return;
        }
        now = ++tot;
        int mid = (l + r) >> 1;
        buildB(a[now].lc , l , mid);
        buildB(a[now].rc , mid + 1 , r);
        addedge(a[now].lc , now , 0);
        addedge(a[now].rc , now , 0);        
}
inline void updateA(int now , int l , int r , int ql , int qr , int u , int w)
{
        if (l == ql && r == qr)
        {
                addedge(u , now , w);
                return;        
        }        
        int mid = (l + r) >> 1;
        if (mid >= qr) updateA(a[now].lc , l , mid , ql , qr , u , w);
        else if (mid + 1 <= ql) updateA(a[now].rc , mid + 1 , r , ql , qr , u , w);
        else
        {
                updateA(a[now].lc , l , mid , ql , mid , u , w);
                updateA(a[now].rc , mid + 1 , r , mid + 1 , qr , u , w);
        }
}
inline void updateB(int now , int l , int r , int ql , int qr , int u , int w)
{
        if (l == ql && r == qr)
        {
                addedge(now , u , w);
                return; 
        }
        int mid = (l + r) >> 1;
        if (mid >= qr) updateB(a[now].lc , l , mid , ql , qr , u , w);
        else if (mid + 1 <= ql) updateB(a[now].rc , mid + 1 , r , ql , qr , u , w);
        else
        {
                updateB(a[now].lc , l , mid , ql , mid , u , w);
                updateB(a[now].rc , mid + 1 , r , mid + 1 , qr , u , w);
        }
}
inline void dijkstra(int s)
{
        priority_queue< pair<ll , ll> , vector< pair<ll , ll> > , greater< pair<ll , ll> > > q;
        dist[s] = 0;
        q.push(make_pair(0 , s));
        while (!q.empty())
        {
                int u = q.top().second;
                q.pop();
                if (visited[u]) continue;
                visited[u] = true;
                for (int i = head[u]; i; i = e[i].nxt)
                {
                        int v = e[i].to , w = e[i].w;
                        if (dist[u] + w < dist[v])
                        {
                                dist[v] = dist[u] + w;
                                q.push(make_pair(dist[v] , v));
                        }
                }
        }
}

int main()
{
        
        read(n); read(q); read(s);
        tot = n;
        buildA(root[0] , 1 , n);
        buildB(root[1] , 1 , n);
        while (q--)
        {
                int type;
                read(type);
                if (type == 1)
                {
                        int u , v , w;
                        read(u); read(v); read(w);
                        addedge(u , v , w);
                }
                if (type == 2)
                {
                        int l , r , v , w;
                        read(v); read(l); read(r); read(w);
                        updateA(root[0] , 1 , n , l , r , v , w);
                } 
                if (type == 3)
                {
                        int l , r , v , w;
                        read(v); read(l); read(r); read(w);
                        updateB(root[1] , 1 , n , l , r , v , w);
                }
        }
        for (int i = 1; i <= tot; i++) dist[i] = inf;
        dijkstra(s);
         for (int i = 1; i <= n; i++) printf("%lld " , dist[i] == inf ? -1 : dist[i]);
        
        return 0; 
    
}

 

转载于:https://www.cnblogs.com/evenbao/p/10146465.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值