[Usaco2005 Dec]Cleaning Shifts

给出n段区间,左右端点分别为\(l_i,r_i\),以及选取这段区间的费用\(c_i\),现在要选出若干个区间,使其完全覆盖区间\([m,e]\),询问费用之和的最小值,\(1≤n≤10000,0≤m≤e≤86399\)。

法一:

不妨把区间按左端点排序,如果在大区间范围外,可以筛除,虽然题目有保障,于是设\(f_i\)表示以第i个区间结尾,覆盖第i个区间前所有需要覆盖的位置的最少代价,于是有

\[f_i=\min_{j=1,r_j+1\geq l_i}^{i-1}\{f_j\}+1
\]

边界:把覆盖大区间左端点全部手动初始化,其余无限大

答案:覆盖了大区间右端点的\(f_i\)

注意到这实际上是\(O(n^2)\)算法,但是因为n比较小,实际上这是\(C_n^2\),其实没有\(10^8\),于是可以水过。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
#define intmax 16843009
using namespace std;
struct interval{
int l,r,c;
il bool operator<(const interval&x)const{
return l<x.l;
}
}I[10001];
int dp[10001];
int main(){
int n,m,e;scanf("%d%d%d",&n,&m,&e);
for(int i(1);i<=n;++i)
scanf("%d%d%d",&I[i].l,&I[i].r,&I[i].c);
sort(I+1,I+n+1),memset(dp,1,sizeof(dp));
ri int i,j;
for(i=1;i<=n;++i)
if(I[i].l==m)dp[i]=I[i].c;
else break;
while(i<=n){
for(j=i-1;j;--j)
if(I[j].r+1>=I[i].l)
if(dp[j]<dp[i])dp[i]=dp[j];
dp[i]+=I[i].c,++i;
}int ans(intmax);
for(i=n;i;--i)
if(I[i].r==e)
if(ans>dp[i])ans=dp[i];
if(ans<intmax)printf("%d",ans);
else puts("-1");
return 0;
}

法二:

注意到只要出题人稍微开大数据范围,就game over了,有水过的痕迹,而且转移也不支持优化,我们只能换状态了,注意到如果法一是正解的,m,e其实可以开到long long范围,但是m,e很小,进入\(nlog^n\)范围,所以意识到可以以位置为状态。

因此设\(f_j\)为覆盖m到j位置的区间的最小费用,区间按右端点排序,枚举区间i,于是不难有

\[f_j=\min_{l_i-1\leq k\leq r_i-1}\{f_{k}\}+c_i
\]

边界:\(f_{m-1}=0\),其余无限大

答案:类似法一

注意到每次我们实际上查询的已求出的f中的某一段的最小值,而已求出的不会被更新,因此我们需要区间查询,于是线段树或者树状数组可以将之优化为\(O(nlog^n)\)

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
#define intmax 16843009
using namespace std;
il int min(int a,int b){
return a<b?a:b;
}
struct interval{
int l,r,c;
il bool operator<(const interval&x)const{
return r<x.r;
}
il void read(){
scanf("%d%d%d",&l,&r,&c),++l,++r;
}
}I[10001];
struct segment_tree{
int a[86400];
struct data{
int l,r,d;
}t[345600];
il void build(int p,int l,int r){
t[p].l=l,t[p].r=r;
if(l==r)return (void)(t[p].d=a[l]);
int mid(l+r>>1),pl(p<<1),pr(pl|1);
build(pl,l,mid),build(pr,mid+1,r);
t[p].d=min(t[pl].d,t[pr].d);
}
il void change(int p,int x,int v){
if(t[p].l==t[p].r)return (void)(t[p].d=v);
int mid(t[p].l+t[p].r>>1),pl(p<<1),pr(pl|1);
if(x<=mid)change(pl,x,v);if(x>mid)change(pr,x,v);
t[p].d=min(t[pl].d,t[pr].d);
}
il int ask(int p,int l,int r){
if(l<=t[p].l&&t[p].r<=r)return t[p].d;
int mid(t[p].l+t[p].r>>1),pl(p<<1),pr(pl|1),ans(intmax);
if(l<=mid)ans=min(ans,ask(pl,l,r));
if(r>mid)ans=min(ans,ask(pr,l,r));
return ans;
}
}T;
int main(){
int n,m,e,i;
scanf("%d%d%d",&n,&m,&e),++m,++e;
for(i=1;i<=n;++i)I[i].read();
sort(I+1,I+n+1),memset(T.a,66,sizeof(T.a));;
T.a[m-1]=0,T.build(1,0,e);
for(i=1;i<=n;++i)
T.change(1,I[i].r,min(T.ask(1,I[i].l-1,I[i].r)+I[i].c,T.ask(1,I[i].r,I[i].r)));
int ans(T.ask(1,e,e));
if(ans>=intmax)puts("-1");
else printf("%d",ans);
return 0;
}

法三:双平衡树

首先鸣谢lsy神犇,提供了这种神奇的思路,优化了法一。

是否还记得法一的\(O(n^2)\)水过?如果我们把m,e变成long long范围,那么你就不得不离散化,这样也就很难写,容易出错,但是除了对位置的考虑,我们还可以对区间尽心考虑,于是我们为了排除无效的决策,把决策集合中的r和dp放入set a,这样当它的r不满足条件,就很容易删除了,但是要查最大的dp值,我们可以把dp单独放入set b,而当r被删除,在set b中找这个dp值,把它删去即可。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>
#define il inline
#define ri register
#define intmax 16843009
using namespace std;
struct pi{
int x,y;
il bool operator<(const pi&a)const{
return x<a.x;
}
};
multiset<pi>A;
multiset<int>B;
struct interval{
int l,r,c;
il bool operator<(const interval&x)const{
return l<x.l;
}
}I[10001];
int dp[10001];
int main(){
int n,m,e;scanf("%d%d%d",&n,&m,&e);
for(int i(1);i<=n;++i)
scanf("%d%d%d",&I[i].l,&I[i].r,&I[i].c);
sort(I+1,I+n+1),memset(dp,1,sizeof(dp));
ri int i;
for(i=1;i<=n;++i)
if(I[i].l==m){
dp[i]=I[i].c,B.insert(dp[i]);
A.insert((pi){I[i].r,dp[i]});
}else break;
while(i<=n){
while(A.size()&&A.begin()->x+1<I[i].l)
B.erase(B.find(A.begin()->y)),A.erase(A.begin());
if(B.size())dp[i]=*B.begin()+I[i].c;
A.insert((pi){I[i].r,dp[i]}),B.insert(dp[i]),++i;
}int ans(intmax);
for(i=n;i;--i)if(I[i].r==e)if(ans>dp[i])ans=dp[i];
if(ans<intmax)printf("%d",ans);else puts("-1");
return 0;
}

[Usaco2005 Dec]Cleaning Shifts的更多相关文章

  1. 【BZOJ1672】[Usaco2005 Dec]Cleaning Shifts 清理牛棚 动态规划

    [BZOJ1672][Usaco2005 Dec]Cleaning Shifts Description Farmer John's cows, pampered since birth, have ...

  2. BZOJ1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚

    1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 414  Solved: ...

  3. BZOJ 1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚

    题目 1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚 Time Limit: 5 Sec  Memory Limit: 64 MB Description Farm ...

  4. BZOJ_1672_[Usaco2005 Dec]Cleaning Shifts 清理牛棚_动态规划+线段树

    BZOJ_1672_[Usaco2005 Dec]Cleaning Shifts 清理牛棚_动态规划+线段树 题意:  约翰的奶牛们从小娇生惯养,她们无法容忍牛棚里的任何脏东西.约翰发现,如果要使这群 ...

  5. P4644 [Usaco2005 Dec]Cleaning Shifts 清理牛棚

    P4644 [Usaco2005 Dec]Cleaning Shifts 清理牛棚 你有一段区间需要被覆盖(长度 <= 86,399) 现有 \(n \leq 10000\) 段小线段, 每段可 ...

  6. [Usaco2005 Dec]Cleaning Shifts 清理牛棚 (DP优化/线段树)

    [Usaco2005 Dec] Cleaning Shifts 清理牛棚 题目描述 Farmer John's cows, pampered since birth, have reached new ...

  7. 【bzoj1672】[USACO2005 Dec]Cleaning Shifts 清理牛棚

    题目描述 Farmer John's cows, pampered since birth, have reached new heights of fastidiousness. They now ...

  8. 洛谷P4644 [USACO2005 Dec]Cleaning Shifts 清理牛棚 [DP,数据结构优化]

    题目传送门 清理牛棚 题目描述 Farmer John's cows, pampered since birth, have reached new heights of fastidiousness ...

  9. 【BZOJ】1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚(dp/线段树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1672 dp很好想,但是是n^2的..但是可以水过..(5s啊..) 按左端点排序后 f[i]表示取第 ...

随机推荐

  1. tomcat服务器和HTTP协议

    tomcat:一个服务器的服务器软件,发布资源要用的 服务器组成: 1.服务器硬件 2.服务器软件 3.项目(一堆资源的集合) 4.资源tomcat本身是一个java程序,必须依赖jre运行eclip ...

  2. java线程池和五种常用线程池的策略使用与解析

    java线程池和五种常用线程池策略使用与解析 一.线程池 关于为什么要使用线程池久不赘述了,首先看一下java中作为线程池Executor底层实现类的ThredPoolExecutor的构造函数 pu ...

  3. zabbix--监控的组件和进程介绍

    上图是zabbix的架构,zabbix proxy(代理),可以减小IO并发. zabbix web GUI是用php写的画图工具,从数据库抓取数据. zabbix database zabbix获取 ...

  4. git 和github简介

    关于github不清楚的可以百度, 在这里,可以创建一个新的仓库 点击Create repository后会出现下面这些信息,其中第一块是仓库的url链接 第二块是你在本地目录中创建一个READEME ...

  5. 调用U9的标准接口

  6. Use on Git

    Preface            The document is about to introduce some specialties on PLM development and mainte ...

  7. JS切换

    这个效果就跟换肤效果差不多 需要准备两套或两套以上的css <!DOCTYPE html> <html lang="en"> <head> &l ...

  8. String.join() --Java8中String类新增方法

    序言 在看别人的代码时发现一个方法String.join(),因为之前没有见过所以比较好奇. 跟踪源码发现源码很给力,居然有用法示例,以下是源码: /** * Returns a new String ...

  9. SharpDx

    layout category title permalink posts_by_category SharpDX SharpDX 系列 /post/sharpdx

  10. Linux/CentOS 7 timezone 修改

    1.su - 登录root用户 2.timedatectl set-timezone {timezone} (set后面加想要设置的时区) 举例:timedatectl set-timezone As ...