Description
给出n个小区间[l,r],更新这段区间的代价为c,求覆盖一段区间[m,e]的最小值。
Solution
线段树优化 dp。
线段树维护区间内最小值,即从 m-1 时刻到 i 时刻要用的最少奶牛。
然后右端点排序,每次查询更新即可。
复杂度 O(挺大)
Code
// By YoungNeal #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 10005 #define M 86650 #define int long long using namespace std; int f[M]; int n,L,R,tot=1; struct NNode{ int l,r,val; friend bool operator<(NNode a,NNode b){ return a.r<b.r; } }cow[N]; struct Node{ int l,r; int minn; int lch,rch; }node[M<<2]; void build(int l,int r,int cur){ if(l==r){ node[cur].l=node[cur].r=l; node[cur].lch=node[cur].rch=-1; node[cur].minn=f[l]; return; } node[cur].lch=++tot; node[cur].rch=++tot; int mid=l+r>>1; build(l,mid,node[cur].lch); build(mid+1,r,node[cur].rch); node[cur].l=node[node[cur].lch].l; node[cur].r=node[node[cur].rch].r; node[cur].minn=min(node[node[cur].lch].minn,node[node[cur].rch].minn); } int query(int l,int r,int cur){ if(l<=node[cur].l&&node[cur].r<=r) return node[cur].minn; int mid=node[cur].l+node[cur].r>>1; int minn=0x3f3f3f3f; if(l<=mid) minn=min(minn,query(l,r,node[cur].lch)); if(mid<r) minn=min(minn,query(l,r,node[cur].rch)); return minn; } void update(int l,int r,int c,int cur){ if(l<=node[cur].l&&node[cur].r<=r){ node[cur].minn=c; return; } int mid=node[cur].l+node[cur].r>>1; if(l<=mid) update(l,r,c,node[cur].lch); if(mid<r) update(l,r,c,node[cur].rch); node[cur].minn=min(node[cur].minn,min(node[node[cur].lch].minn,node[node[cur].rch].minn)); } signed main(){ scanf("%lld%lld%lld",&n,&L,&R),L++,R++; for(int i=1;i<=n;i++) scanf("%lld%lld%lld",&cow[i].l,&cow[i].r,&cow[i].val),cow[i].l++,cow[i].r++; sort(cow+1,cow+1+n); memset(f,0x3f,sizeof f); f[L-1]=0; build(L-1,R,1); for(int i=1;i<=n;i++){ int minn=query(cow[i].l-1,cow[i].r-1,1); if(minn+cow[i].val<f[cow[i].r]){ f[cow[i].r]=minn+cow[i].val; update(cow[i].r,cow[i].r,f[cow[i].r],1); } } printf(f[R]>=0x3f3f3f3f?"-1":"%lld ",f[R]); return 0; }