《演算法競賽進階指南》0x58資料結構優化DP AcWing296 擴充套件最小花費區間覆蓋
阿新 • • 發佈:2020-08-02
題目連結: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; }