题目描述
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 没有额外限制。