洛谷P7984 [USACO21DEC] Tickets P

题目描述

Bessie 正在参加远足旅行!她当前正在旅行的路线由编号为 1…𝑁1…N(1≤𝑁≤1051≤N≤105)的 𝑁N 个检查点组成。

有 𝐾K(1≤𝐾≤1051≤K≤105)张票可供购买。第 𝑖i 张票可以在检查站 𝑐𝑖ci​(1≤𝑐𝑖≤𝑁1≤ci​≤N)以 𝑝𝑖pi​(1≤𝑝𝑖≤1091≤pi​≤109)的价格购得,并且可以用其进入所有检查站 [𝑎𝑖,𝑏𝑖][ai​,bi​](1≤𝑎𝑖≤𝑏𝑖≤𝑁1≤ai​≤bi​≤N)。在进入任何检查站之前,Bessie 必须已购买一张允许其进入该检查站的票。一旦 Bessie 可以前往某一检查站,她就可以在未来的任何时候回到该检查站。

对于每一个 𝑖∈[1,𝑁]i∈[1,N],如果 Bessie 最初只能进入检查点 𝑖i,输出使得可以进入检查点 11 和 𝑁N 所需的最低总价。如果无法这样做,输出 −1−1。

输入格式

输入的第一行包含 𝑁N 和 𝐾K。

以下 𝐾K 行,对于每一个 1≤𝑖≤𝐾1≤i≤K,第 𝑖i 行包含四个整数 𝑐𝑖ci​,𝑝𝑖pi​,𝑎𝑖ai​ 和 𝑏𝑖bi​。

输出格式

输出 𝑁N 行,每行输出一个检查点的答案。

输入输出样例

输入 #1

7 6
4 1 2 3
4 10 5 6
2 100 7 7
6 1000 1 1
5 10000 1 4
6 100000 5 6

输出 #1

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define ll long long
using namespace std;
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
const int N=1e6+5,M=7e6+5;
const ll inf=1e16;
int head[N],cnt;
struct Edge{
    int to,nxt,w;
}e[M];
inline void add(int u,int v,int w){e[++cnt]={v,head[u],w};head[u]=cnt;}
int n,q,s;
struct Node{int l,r;}t[N];
#define ls (p<<1)
#define rs (ls|1)
inline void build(int p,int l,int r){
    t[p].l=l,t[p].r=r;
    if(l==r){//叶子节点与原图加边
        add(l+8*n,p,0);add(p+4*n,l+8*n,0);
        add(p,l+8*n,0);add(l+8*n,p+4*n,0);
        return;
    }
    //向儿子连边
    add(p,ls,0);add((ls)+4*n,p+4*n,0);
    add(p,rs,0);add((rs)+4*n,p+4*n,0);
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
}
inline void upd(int p,int L,int R,int u,int w){
    int l=t[p].l,r=t[p].r,mid=(l+r)>>1;
    if(l==L&&r==R){//当前节点覆盖区间
        add(p+4*n,u+8*n,w);
        return;
    }
    if(R<=mid)upd(ls,L,R,u,w);
    else if(L>mid)upd(rs,L,R,u,w);
    else{
        upd(ls,L,mid,u,w);upd(rs,mid+1,R,u,w);
    }
}
ll dis[N],d[N];
struct node{
    ll dis;int pos;
    bool operator <( const node &x )const{
        return x.dis < dis;
    }
};
bool vis[N];
priority_queue <node> pq;
inline void dijkstra(bool op=0){
    if(!op){
        memset(dis,0x3f,sizeof(dis));
        dis[s]=0;pq.push({0,s});
    }else{
        rep(i,1,9*n+q)pq.push({dis[i],i});
    }
    memset(vis,0,sizeof(vis));
    while(!pq.empty()){
        node tmp=pq.top();pq.pop();
        int x=tmp.pos;
        if(vis[x])continue;
        vis[x]=1;
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(dis[y]>dis[x]+e[i].w){
                dis[y]=dis[x]+e[i].w;
                pq.push({dis[y],y});
            }
        }
    }
}
int main(){
    n=read(),q=read();
    build(1,1,n);
    rep(i,1,q){
        int a=read(),w=read(),b=read(),c=read();
        upd(1,b,c,i+n,0);
        add(9*n+i,a+8*n,w);
    }
    s=8*n+1;
    dijkstra();
    memcpy(d,dis,sizeof(d));
    //rep(i,1,n)cout<<dis[i+8*n]<<' ';
    s=9*n;
    dijkstra();
    rep(i,1,9*n+q)dis[i]+=d[i];
    dijkstra(1);
    rep(i,1,n){
        if(dis[i+8*n]>inf)puts("-1");
        else printf("%lld\n",dis[i+8*n]);
    }
    return 0;
}
-1
-1
-1
1111
10100
110100
-1

说明/提示

【样例解释】

如果 Bessie 从检查点 𝑖=4i=4 开始,那么一种购得进入检查点 11 和 𝑁N 的方法如下:

在检查点 44 购买第一张票,使 Bessie 可以进入检查点 22 和 33。

在检查点 22 购买第三张票,使 Bessie 可以进入检查点 77。

回到检查点 44 购买第二张票,使 Bessie 可以进入检查点 55 和 66。

在检查点 66 购买第四张票,使 Bessie 可以进入检查点 11。

【数据范围】

  • 测试点 1-7 满足 𝑁,𝐾≤1000N,K≤1000。
  • 测试点 8-19 没有额外限制。
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值