Cleaning Shifts[线段树+DP]

传送门


区间覆盖问题 , f[x]表示覆盖L--x的最少代价

f[r[i]]=min(f[x])+s[i](l[i]-1<=x<r[i])

线段树维护区间最小


//未ac但对拍过的代码
#include<cstdio>
#include<algorithm>
#define N 10050
#define M 100050
#define LL long long 
#define inf 1000000000000000
using namespace std;
int n,L,R; LL f[M];
struct Tree{int l,r; LL val;}t[M<<2];
struct Node{int l,r,s;}a[N];
bool cmp(Node a,Node b){return a.r<b.r;}
void Pushup(int x){
	t[x].val = min(t[x<<1].val , t[x<<1|1].val);
}
void build(int x,int l,int r){
	t[x].l=l , t[x].r=r;
	if(l==r){
		if(l>=L) t[x].val = inf; return;
	}
	int mid=(l+r)>>1;
	build(x<<1,l,mid) , build(x<<1|1,mid+1,r);
	Pushup(x);
}
LL Quary(int x,int L,int R){
	if(L<=t[x].l && t[x].r<=R) return t[x].val;
	int mid=(t[x].l+t[x].r)>>1; LL ans=inf;
	if(L<=mid) ans=min(ans,Quary(x<<1,L,R));
	if(R>mid) ans=min(ans,Quary(x<<1|1,L,R));
	return ans;
} 
void Update(int x,int pos,LL val){
	if(t[x].l==t[x].r){t[x].val=val;return;}
	int mid=(t[x].l+t[x].r)>>1;
	if(pos<=mid) Update(x<<1,pos,val);
	else Update(x<<1|1,pos,val);
	Pushup(x);
} 
int main(){
	scanf("%d%d%d",&n,&L,&R);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].s);
		if(a[i].l<L) a[i].l=L; 
		if(a[i].r>R) a[i].r=R;
	}
	build(1,0,R); for(int i=1;i<=R;i++) f[i]=inf;
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;i++){
		if(a[i].r<=L) continue;
		LL x=Quary(1,a[i].l-1,a[i].r);
		if(x+a[i].s < f[a[i].r]){
			f[a[i].r] = x+a[i].s;
			Update(1,a[i].r,f[a[i].r]);
		} 
	}
	if(f[R]==inf){printf("-1"); return 0;}
	printf("%lld",f[R]); return 0;
}

猜你喜欢

转载自blog.csdn.net/sslz_fsy/article/details/84205102
今日推荐