题目

你知道Just Odd Inventions社吗?这个公司的业务是“只不过是奇妙的发明(Just Odd Inventions)”。这里简称为JOI社。

JOI社有N名员工,编号从1到N。所有员工的工作时间从时刻0持续到时刻M,时刻0和时刻M的时候,所有员工都必须在公司内。

某天,出于巧合,JOI社的每个员工都要出行恰好一次。员工i(1<=i<=N)在时刻Si离开公司,时刻Ti回到公司。同一时刻不会同时有两名以上的员工离开或回到公司。

JOI社的入口处有一扇巨大的门,员工只能通过这扇门离开或回到公司。门上挂着一把锁,从公司内部可以任意开锁或上锁,但从公司外部只有持有备用钥匙的人才能开锁或者上锁。时刻0时,锁是锁上的。

每个社员在回到公司的时候,都必须能够进入公司。换句话说,对于任意1<=i<=N,要么员工i持有备用钥匙,要么时刻Ti时门是开着的,否则是不被允许的。员工回到公司的时候,或者携带备用钥匙的员工离开公司的时候,可以选择锁门或不锁。没有携带备用钥匙的员工离开公司的时候没有办法锁门。

JOI社的社长决定把备用钥匙交给N个员工中的K个人。为了避免钥匙的丢失,员工之间不允许借用钥匙。此外,JOI社的社长很重视时间效率,因此每个员工在离开或回到公司的时刻以外,不允许开锁或者上锁。

出于安全的考虑,社长希望上锁的时间越长越好。现在他将员工出入公司的信息和准备交给员工的钥匙数量告诉了你,请你求出在能使所有员工回到公司的时候都能进入公司的大门的前提下,上锁的时间最长是多少。

分析

首先把所有进出时间都放在坐标系下,发现相邻的两个点会有4种情况:

第一种:左出右出

只需要左端点那个人带钥匙该区间便可以获得其中的值。

第二种:左进右进

右端点那个人带钥匙该区间便可以获得其中的值。

第三种:左进右出

都不用拿,直接计入答案。

第四种:左出右进

两人都带钥匙该区间便可以获得其中的值。

对于前两种情况,设v[i]表示当i这个人拿了钥匙时,可以给答案贡献多少;

而第四种情况,可以将两个人连一条边,然后就会发现很多个联通块,而且都是以一条链的形式。

然后,所有的链排在一起,给每一个点按位置一个新的编号。

问题转化为,有n个点,选取每个点有得分,并且同时选取一个点以及它的上一个点有额外得分,求选出k 个点的最高得分。

就可以用dp解决:

f[i][j]表示前i个点,选了j个点,其中包括i,的最大得分;

f[i][j]=max(max(f[1~i-2][j-1]),f[i-1][j-1]+当选取了i-1和i时可以获得的额外得分)+v[i]

其中max(f[1~i-2][j-1])可以开一个动态数组表示:

g[j]表示当前做到i的max(f[1~i-2][j])。

然后就变成了

f[i][j]=max(g[j-1],f[i-1][j-1]+当选取了i-1和i时可以获得的额外得分)+v[i]

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
using namespace std;
int g[4005],v[4005],tog[4005],f[4005][4005],b[4005][5],n,m,tot,ans,k,mx,d[4005],next[4002];
bool bz[4002];
void q(int l,int r)
{
int i=l,j=r,mid=b[(l+r)/2][2],e;
while(i<j)
{
while(b[i][2]<mid) i++;
while(b[j][2]>mid) j--;
if(i<=j)
{
e=b[i][2];
b[i][2]=b[j][2];
b[j][2]=e;
e=b[i][0];
b[i][0]=b[j][0];
b[j][0]=e;
e=b[i][1];
b[i][1]=b[j][1];
b[j][1]=e;
i++;
j--;
}
}
if(i<r) q(i,r);
if(l<j) q(l,j);
}
int dg(int x)
{
if(!x)
return 0;
bz[x]=false;
dg(next[x]);
d[d[0]--]=x;
}
int main()
{
int i;
scanf("%d%d%d",&n,&m,&k);
tot=0;
for(i=1;i<=n;i++)
{
scanf("%d",&b[++tot][2]);
b[tot][1]=i;
b[tot][0]=0;
scanf("%d",&b[++tot][2]);
b[tot][1]=i;
b[tot][0]=1;
}
q(1,tot);
ans=0;
memset(bz,true,sizeof(bz));
for(i=1;i<=tot-1;i++)
{
int x=b[i][0]*10+b[i+1][0];
if(x==0)
{
v[b[i][1]]+=b[i+1][2]-b[i][2];
}
else
if(x==11)
{
v[b[i+1][1]]+=b[i+1][2]-b[i][2];
}
else
if(x==10)
{
ans+=b[i+1][2]-b[i][2];
}
else
{
if(b[i][1]!=b[i+1][1])
{
next[b[i][1]]=b[i+1][1];
bz[b[i+1][1]]=false;
tog[b[i+1][1]]=b[i+1][2]-b[i][2];
}
else
{
v[b[i][1]]+=b[i+1][2]-b[i][2];
}
}
}
ans+=b[1][2];
ans+=m-b[tot][2];
d[0]=n;
for(i=1;i<=n;i++)
if(bz[i])
dg(i);
for(i=1;i<=n;i++)
{
for(int j=1;j<=k;j++)
{
if(j>1)
f[i][j]=max(g[j-1],f[i-1][j-1]+tog[d[i]]);
f[i][j]+=v[d[i]];
g[j]=max(g[j],f[i-1][j]);
mx=max(mx,f[i][j]);
}
}
printf("%d\n",mx+ans);
}

【NOIP2015模拟11.3】备用钥匙的更多相关文章

  1. JZOJ 4298. 【NOIP2015模拟11.2晚】我的天

    4298. [NOIP2015模拟11.2晚]我的天 (File IO): input:ohmygod.in output:ohmygod.out Time Limits: 1000 ms Memor ...

  2. 【NOIP2015模拟11.5】JZOJ8月5日提高组T2 Lucas的数列

    [NOIP2015模拟11.5]JZOJ8月5日提高组T2 Lucas的数列 题目 PS:\(n*n*T*T<=10^{18}\)而不是\(10^1*8\) 题解 题意: 给出\(n\)个元素的 ...

  3. 【NOIP2015模拟11.5】JZOJ8月5日提高组T1 俄罗斯套娃

    [NOIP2015模拟11.5]JZOJ8月5日提高组T1 俄罗斯套娃 题目 题解 题意就是说 将1~\(n\)排列,问有多少种方案使得序列的逆序对个数小于\(k\) 很容易想到DP 设\(f[i][ ...

  4. 【NOIP2015模拟11.2晚】JZOJ8月4日提高组T2 我的天

    [NOIP2015模拟11.2晚]JZOJ8月4日提高组T2 我的天 题目 很久很以前,有一个古老的村庄--xiba村,村子里生活着n+1个村民,但由于历届村长恐怖而且黑暗的魔法统治下,村民们各自过着 ...

  5. 【NOIP2015模拟11.4】JZOJ2020年8月6日提高组T2 最优交换

    [NOIP2015模拟11.4]JZOJ2020年8月6日提高组T2 最优交换 题目 题解 题意 有一个长度为\(n\)的正整数 最多可以进行\(k\)次操作 每次操作交换相邻两个位置上的数 问可以得 ...

  6. 【NOIP2015模拟11.4】JZOJ8月6日提高组T1 刷题计划

    [NOIP2015模拟11.4]JZOJ8月6日提高组T1 刷题计划 题目 题解 题意 有\(n\)道题,编号为1~\(n\) 给出\(m\)次操作 每次操作有3种类型 1 \(x\) 表示交了\(A ...

  7. 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行

    [NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...

  8. JZOJ4307. 【NOIP2015模拟11.3晚】喝喝喝

    Description

  9. [JZOJ 4307] [NOIP2015模拟11.3晚] 喝喝喝 解题报告

    题目链接: http://172.16.0.132/senior/#main/show/4307 题目: 解题报告: 题目询问我们没出现坏对的连续区间个数 我们考虑从左到有枚举右端点$r$,判断$a[ ...

随机推荐

  1. Monkey测试:启动adb shell失败

    1.在dos环境下输入adb shell 2.遇到adb server version doesn't match this client:killing错误 如: 3.在遇到如上问题时,输入adb ...

  2. VS2012下std::function的BUG解决办法

    VS2012版本下std::function存在问题,链接:https://stackoverflow.com/questions/13096162/stdfunction-not-compiling ...

  3. 一次性计划任务at与周期性计划任务crontab

    一.at一次性计划任务使用 at语法格式: at 时间 at设置计划任务 1.下载at程序 [root@li ~]# yum install at -y 2.启动atd服务 [root@li ~]# ...

  4. ELk架构解析和部署

    目录 一.什么是elk. 1 二.ELK 常用架构及使用场景介绍... 2 1.最简单架构... 2 2.以Logstash 作为日志搜集器... 2 3.以Beats 作为日志搜集器... 3 4. ...

  5. linux最强编辑神器vim常用命令大全:编辑、插入、删除、替换、保存...

    我说vim是编辑器之神大家没有意见吧 下面分享一些vim常用命令,大家可以收藏一下 进入vim:  vim配置: vim中光标移动: vim中屏幕滚动: vim中插入文本类: 文本替换: 格式 : 范 ...

  6. 解决org.apache.subversion.javahl.ClientException的方法【】

    重新刷新项目,配置项目,总是报“The project was not built due to "org.apache.subversion.javahl.ClientException” ...

  7. Spring MVC-学习笔记(4)数据绑定流程

    1.请求数据在到达处理方法前这段时间. spring MVC还会做请求信息转换.数据转换.数据格式化.数据校验. 2.数据转换 1>ConversionService: Spring类型转换体系 ...

  8. 关于this与e.target区别以及data-*属性

    1 this与event.target 在编写事件函数时可以传入一个event参数,even参数可以使用一个target属性如even.target用以调用,其作用是指向返回事件的目标节点(触发该事件 ...

  9. 掌握这些 Redis 技巧,百亿数据量不在话下!

    一.Redis封装架构讲解 实际上NewLife.Redis是一个完整的Redis协议功能的实现,但是Redis的核心功能并没有在这里面,而是在NewLife.Core里面. 这里可以打开看一下,Ne ...

  10. PHP 经典有趣的算法

    原文:https://blog.csdn.net/a519395243/article/details/77942913 1.一群猴子排成一圈,按1,2,…,n依次编号.然后从第1只开始数,数到第m只 ...