注意到“覆盖”并不好处理,我们只需保证:
- 有一个 \([1,p]\)
- 有一个 \([q,n]\)
- 没有空隙
根据套路,设 \(f_ i\) 表示考虑所有完全在 \([1,r_i]\) 中的区间使得中间没有空隙的最小代价。
转移限制为 \(r_i-l_j+1\geq |T_i-T_j|\),方程为 \(f_i+c_j\rightarrow f_j\)
这是一个最短路,使用 Dijkstra 即可,更新时用线段树找点。
由于 \(c_j\) 恒定,所以 \(f_j\) 只会在第一次被更新,只需要在更新一次后将其置为不可访问即可。
#include <cstdio>
#include <cctype>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
using ll=long long;
using pli=pair<ll, int>;
#define mk make_pair
char buf[1<<14], *p1=buf, *p2=buf;
#define GetC() ((p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++)
struct Ios{}io;
template <typename _tp>
Ios &operator >>(Ios &in, _tp &x){
x=0; int w=0; char c=GetC();
for(;!isdigit(c);w|=c=='-', c=GetC());
for(;isdigit(c);x=x*10+(c^'0'), c=GetC());
if(w) x=-x;
return in;
}
const int N=1e5+5;
const ll inf=1e18;
int n, m;
ll ans=inf;
struct qwq{ int t, l, r, c; }a[N];
priority_queue <pli, vector<pli>, greater<pli> > q;
ll mn1[N<<2], mn2[N<<2];
void up(int p){
mn1[p]=min(mn1[p<<1], mn1[p<<1|1]);
mn2[p]=min(mn2[p<<1], mn2[p<<1|1]);
}
void build(int p, int l, int r){
if(l==r){
mn1[p]=a[l].l-a[l].t;
mn2[p]=a[l].l+a[l].t;
return ;
}
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
up(p);
}
ll d;
void updateL(int p, int l, int r, int limp, int limv){
if(mn1[p]>limv) return ;
if(l==r){
q.push(mk(d+a[l].c, l));
mn1[p]=mn2[p]=inf;
return ;
}
int mid=(l+r)>>1;
updateL(p<<1, l, mid, limp, limv);
if(mid<limp) updateL(p<<1|1, mid+1, r, limp ,limv);
up(p);
}
void updateR(int p, int l, int r, int limp, int limv){
if(mn2[p]>limv) return ;
if(l==r){
q.push(mk(d+a[l].c, l));
mn1[p]=mn2[p]=inf;
return ;
}
int mid=(l+r)>>1;
if(mid>=limp) updateR(p<<1, l, mid ,limp, limv);
updateR(p<<1|1, mid+1, r, limp, limv);
up(p);
}
void dij(){
for(int i=1;i<=m;++i) if(a[i].l==1) q.push(mk(a[i].c, i));
while(!q.empty()){
pli u=q.top(); q.pop();
int x=u.second; d=u.first;
if(a[x].r==n) ans=min(ans, d);
if(x>1) updateL(1, 1, m, x-1, a[x].r-a[x].t+1);
if(x<m) updateR(1, 1, m, x+1, a[x].r+a[x].t+1);
}
}
int main(){
io>>n>>m;
for(int i=1;i<=m;++i)
io>>a[i].t>>a[i].l>>a[i].r>>a[i].c;
sort(a+1, a+m+1, [](qwq x, qwq y){ return x.t<y.t; });
build(1, 1, m);
dij();
if(ans!=inf) printf("%lld\n", ans);
else puts("-1");
return 0;
}
标签:return,int,Day4,GetC,JOISC,2020,inf,include,ll
From: https://www.cnblogs.com/pref-ctrl27/p/17089946.html