《算法竞赛进阶指南》0x58数据结构优化DP AcWing296 扩展最小花费区间覆盖

题目链接: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;
}

 

posted @ 2020-08-02 10:59  WA自动机~  阅读(123)  评论(0编辑  收藏  举报