- 将目标区间[m,e]转换为[1,e-m+1],同时转换每个奶牛的工作区间。
- dp[i]表示覆盖区间[1,i]所需最小代价,dp[T2]=min(dp[i]+s),T1-1<=i<=T2-1。
- 状态转移方程涉及区间查询最小值,因此可以丢进线段树维护。时间复杂度O(ne)降至O(nloge)。
- 初始将cow按T2从小到大排序,segmenttree[0,0]=0。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=10005,maxm=88000;
int n,m,e;
long long tree[maxm*4];
struct cow{
int lef,rig,cos;
bool operator<(const cow &a)const{
return lef<a.lef;
}
}c[maxn];
bool cmp(cow a,cow b)
{
return a.rig<b.rig;
}
void pushup(int x,int l,int r)
{
tree[x]=min(tree[x<<1],tree[x<<1|1]);
}
void inserts(int x,int l,int r,int ll,int rr,long long k)
{
if(r<ll||l>rr) return ;
if(l>=ll&&r<=rr)
{
tree[x]=min(k,tree[x]);
return;
}
int mid=(l+r)>>1;
inserts(x<<1,l,mid,ll,rr,k);
inserts(x<<1|1,mid+1,r,ll,rr,k);
pushup(x,l,r);
}
long long query(int x,int l,int r,int ll,int rr)
{
if(r<ll||l>rr) return 1e10;
if(l>=ll&&r<=rr)
return tree[x];
int mid=(l+r)>>1;
return min(query(x<<1,l,mid,ll,rr),query(x<<1|1,mid+1,r,ll,rr));
}
int main()
{
for(int i=1;i<=4*maxm-1;i++) tree[i]=1e10;
scanf("%d%d%d",&n,&m,&e);
e-=(m-1);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&c[i].lef,&c[i].rig,&c[i].cos);
c[i].lef-=(m-1);
c[i].rig-=(m-1);
}
sort(c+1,c+1+n,cmp);
inserts(1,0,e,0,0,0);
for(int i=1;i<=n;i++)
{
long long ans=query(1,0,e,c[i].lef-1,c[i].rig-1);
if(ans==1e10) continue;
inserts(1,0,e,c[i].rig,c[i].rig,ans+c[i].cos);
}
cout<<(query(1,0,e,e,e)==1e10?-1:query(1,0,e,e,e));
return 0;
}