[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. UI自动化ADB出现devices offline的解决方法

    终端运行如下命令即可解决: adb kill-server adb start-server adb remount

  2. python不同包之间调用时提示文件模块不存在的问题

    python对于跨包调用函数时,经常会提示模块不存在的问题,主要是python程序执行时,搜索路径导致的,python程序执行的路径依次是: (1)程序根目录(2)环境变量(3)标准库目标(D:\Py ...

  3. python全栈开放实践第三版第一章的练习题完成情况

    练习题: 1.简述编译型与解释型语言的区别,且分别列出你知道哪些语言属于编译型,哪些数以解释型.1 编译型:只须编译一次就可以把源代码编译成机器语言,后面的执行无须重新编译,直接使用之前的编译结果就可 ...

  4. .Net平台调用の初识

    前言 工作过程中难免遇到混合编程,现在我们要谈的是C#和c++语言的编程.C#要调用C++的库目前可选主要有两种方式:Com技术和平台调用(P/Invoke).现在我们要谈的是P/Invoke技术. ...

  5. 使用tensorboard报错 ImportError: No module named past.builtins

    安装 future pip install future conda install future

  6. 解决mac下,javac命令出现的乱码问题

    今天突然检查我的jdk安装,发现出现了乱码 一,出现乱码

  7. [LOJ#6468.] 魔法

    官方题解 看了题解才会做.. 首先考虑如果所有询问的点都是[1,n]的做法,如果询问是[l,r]只需要把多余的去掉就好了 然后要把问题转化为一个点对其他附近的点的贡献 记$pre[i]$为第i个位置的 ...

  8. Mysql流程解析

    Mysql流程解析 流程图 流程图解析 客户端发送一条sql语句. 1.此时,mysql会检查sql语句,查看是否命中缓存,如果命中缓存,直接返回结果,不继续执行.没有命中则进入解析器. 2.解析器会 ...

  9. robotframework+python3+selenium之创建第一个项目---第三集

    1.新建一个project 选择Directory,则是文件夹 2.选择文件,创建new suite    test_1 3.创建test case   baidu_test 4.此时界面如图: 5. ...

  10. loj2001[SDOI2017]树点染色

    题意:给你一棵树,一开始每个点上的颜色互不相同.三种操作:op1:x到根的路径上的点都染上一种新的颜色.op2:设一条路径的权值为val(x,y),求x到y路径的val.op3:询问x的子树中最大的到 ...