BZOJ1672 Cleaning Shifts 清理牛棚

传送门

显然可以考虑 $dp$

设 $f[i]$ 表示当前到了时间 $i$,从初始到 $i$ 的时间都安排好打扫了

把所有牛按照区间 $l,r$ 双关键字排序

这样枚举到一头牛 $x$ 时,在 $x.l$ 之前的牛都考虑完了($x.l$ 是牛 $x$ 的左区间)

然后枚举 $[x.l-1,x.r]$ 之间的时间 $y$,有转移 $f[x.r]=min(f[x.r],f[y]+x.c)$ ($x.r$ 是牛 $x$ 的右区间,$x.c$ 是牛$x$ 的花费)

这样转移才能保证从开始时间一直到 $x.r$ 都有牛打扫

$x.l-1$ 是因为每头牛打扫的时间是闭区间,$[a,b]+[b+1,c]$ 的方案是合法的

然后这个东西的转移直接用线段树区间求 $min$ 和单点取 $min$ 就行了

具体看代码吧,注意区间可能为 $0$,写线段树的时候区间下标统一加一就行

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=1e5+7;
int n,S,E;
ll T[N<<2],tag[N<<2];
inline void pushdown(int o,int l,int r)
{
    if(!o||tag[o]==T[0]) return;
    T[o]=min(T[o],tag[o]);
    if(l==r) { tag[o]=T[0]; return; }
    tag[o<<1]=min(tag[o<<1],tag[o]);
    tag[o<<1|1]=min(tag[o<<1|1],tag[o]);
    tag[o]=T[0];
}
int ql,qr;
ll K,res;
inline void change(int o,int l,int r)
{
    pushdown(o,l,r);
    if(l>qr||r<ql) return;
    if(l>=ql&&r<=qr) { tag[o]=K; pushdown(o,l,r); return; }
    int mid=l+r>>1;
    change(o<<1,l,mid); change(o<<1|1,mid+1,r);
    T[o]=min(T[o<<1],T[o<<1|1]);
}
inline void query(int o,int l,int r)
{
    pushdown(o,l,r);
    if(l>qr||r<ql) return;
    if(l>=ql&&r<=qr) { res=min(res,T[o]); pushdown(o,l,r); return; }
    int mid=l+r>>1;
    query(o<<1,l,mid); query(o<<1|1,mid+1,r);
    T[o]=min(T[o<<1],T[o<<1|1]);
}
struct dat{
    int l,r,c;
    inline bool operator < (const dat &tmp) const { return l<tmp.l; }
}d[N];
int main()
{
    memset(T,0x3f,sizeof(T));
    memset(tag,0x3f,sizeof(tag));
    n=read(),S=read()+1,E=read()+1;
    for(int i=1,a,b,c;i<=n;i++)
    {
        a=read()+1,b=read()+1,c=read();
        d[i]=(dat){a,b,c};
    }
    sort(d+1,d+n+1);
    ql=d[1].r,qr=d[1].r,K=d[1].c; change(1,1,E);
    for(int i=2;i<=n;i++)
    {
        res=T[0]; ql=max(S,d[i].l-1); qr=d[i].r; query(1,1,E);
        if(res==T[0]) continue;
        K=res+d[i].c; ql=d[i].r; qr=d[i].r; change(1,1,E);
    }
    res=T[0]; ql=qr=E; query(1,1,E);
    if(res==T[0]) printf("-1\n");
    else printf("%lld\n",res);
    return 0;
}

 

posted @ 2019-08-08 18:34  LLTYYC  阅读(118)  评论(0编辑  收藏  举报