题目链接:https://www.acwing.com/problem/content/298/
题目给定一个长区间[m,e]和一些短区间,短区间上有花费,问覆盖长区间的最小话费是多少?
通过dp可以在最少区间数模型上进行修改,转移的时候算上的是花费值,最后用线段树维护一下区间最小值即可。时间复杂度是O(nlogn+nlog(e-m))。
代码:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N = 10010,T=90000; const int inf=1e9; struct Range{ int l,r,w; bool operator < (const Range& b)const{ return r<b.r; } }range[N]; struct node{ int l,r,v; }t[T<<2]; int n,m,e; void pushup(int rt){ t[rt].v=min(t[rt<<1].v,t[rt<<1|1].v); } void build(int rt,int l,int r){ t[rt]={l,r,inf}; if(l==r)return; int mid=l+r>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); } void update(int rt,int pos,int C){ if(t[rt].l==t[rt].r){ t[rt].v=min(t[rt].v,C); return; } int mid=t[rt].l+t[rt].r>>1; if(pos<=mid)update(rt<<1,pos,C); else update(rt<<1|1,pos,C); pushup(rt); } int query(int rt,int L,int R){ if(t[rt].l>=L && t[rt].r<=R)return t[rt].v; int mid=t[rt].l+t[rt].r>>1; int res=inf; if(L<=mid)res=min(res,query(rt<<1,L,R)); if(R>mid)res=min(res,query(rt<<1|1,L,R)); return res; } int main(){ cin>>n>>m>>e; build(1,m-1,e); for(int i=1;i<=n;i++) scanf("%d%d%d",&range[i].l,&range[i].r,&range[i].w); sort(range+1,range+n+1); update(1,m-1,0); for(int i=1;i<=n;i++){ int l=range[i].l, r=range[i].r,w=range[i].w; int val=query(1,l-1,r-1)+w; update(1,r,val); } int res=query(1,e,e); if(res==inf)res=-1; cout<<res<<endl; return 0; }