Codeforces787B. Not Afraid

题目链接:https://codeforces.com/contest/787/problem/B

题目给出三种询问,如果暴力建边很显然复杂度过大,参考线段树优化建边,加虚点即可完成

参考博文:https://www.luogu.org/blog/chengni5673/tu-lun-di-xiao-ji-qiao-yi-ji-kuo-zhan

#include <bits/stdc++.h>
#define pii pair<ll, ll>
#define pil pair<ll, long long>
#define pll pair<long long, long long>
#define lowbit(x) ((x)&(-x))
#define mem(i, a) memset(i, a, sizeof(i))
#define sqr(x) ((x)*(x))
#define all(x) x.begin(),x.end()
#define ls (k << 1)
#define rs (k << 1 | 1)
using namespace std;
typedef long long ll;
template <typename T>
inline void read(T &X) {
    X = 0; char ch = 0; T op = 1;
    for(; ch > '9' || ch < '0'; ch = getchar())
        if(ch == '-') op = -1;
    for(; ch >= '0' && ch <= '9'; ch = getchar())
        X = (X << 3) + (X << 1) + ch - 48;
    X *= op;
}

const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll N = 5e5 + 5;
struct edge {
    ll u,v,w,next;
}e[N << 2];
struct node {
    ll num[N];
}tr[2];
ll vis[N],dis[N],cnt,head[N];
ll n,q,s,now;
void insert(ll u, ll v, ll w) {
    e[++cnt] = {u, v, w, head[u]}; head[u] = cnt;
}
void dijkstra() {
    priority_queue<pii, vector<pii>, greater<pii> > q;
    mem(dis, INF);
    q.push(make_pair(0, s)); dis[s] = 0;
    while(!q.empty()) {
        ll u = q.top().second; q.pop();
        if(vis[u]) continue; vis[u] = 1;
        for(ll i = head[u]; i ; i = e[i].next) {
            ll v = e[i].v;
            if(dis[v] > dis[u] + e[i].w) {
                dis[v] = dis[u] + e[i].w;
                q.push(make_pair(dis[v], v));
            }
        }
    }
    return;
}
void build(ll k, ll l, ll r, ll p) {
    if(l == r) {
        tr[p].num[k] = l;
        return;
    }
    tr[p].num[k] = ++now;
    ll mid = l + r >> 1;
    build(ls, l, mid, p);
    build(rs, mid + 1, r, p);
    if(p == 0) {
        insert(tr[p].num[k], tr[p].num[ls], 0);
        insert(tr[p].num[k], tr[p].num[rs], 0);
    } else {
        insert(tr[p].num[ls], tr[p].num[k], 0);
        insert(tr[p].num[rs], tr[p].num[k], 0);
    }
}
void find(ll k, ll l, ll r, ll s, ll t, ll p, ll u, ll w) {
    if(s <= l && t >= r) {
        if(p == 0) insert(u, tr[p].num[k], w);
        else insert(tr[p].num[k], u, w);
        return;
    }
    ll mid = l + r >> 1;
    if(s <= mid) find(ls, l, mid, s, t, p, u, w);
    if(t > mid) find(rs, mid + 1, r, s, t, p, u, w);
    return;
}
int main() {
#ifdef INCTRY
    freopen("input.txt", "rt", stdin);
#endif
    cin >> n >> q >> s;
    now = n;
    build(1, 1, n, 0); build(1, 1, n, 1);
    while(q--) {
        ll t,u,v,w,c,l,r;
        read(t);
        //cout << q << " ";
        if(t == 1) {
            read(u); read(v); read(w); 
            insert(u, v, w);
        } else {
            read(u); read(l); read(r); read(w);
            if(t == 2) {
                find(1, 1, n, l, r, 0, u, w);
            } else {
                find(1, 1, n, l, r, 1, u, w);
            }
        }
    }
    dijkstra();
    for(ll i = 1; i <= n; i++) {
        cout << (dis[i] == INF ? -1 : dis[i]) << " " ;
    }


#ifdef INCTRY
    cerr << "\nTime elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

转载于:https://www.cnblogs.com/inctry/p/11300501.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值