题目

你知道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. 阶段3 1.Mybatis_06.使用Mybatis完成DAO层的开发_2 Mybatis中编写dao实现类的使用-保存操作

    再完善.saveUser的方法 测试保存的操作 报错了 SqlSession的insert的源码 我们在执行Insert的时候,并没有把user对象传过去 usersex改成sex 再次测试

  2. PyQt5学习一---环境的安装和配置

    PyQt5环境安装 1.Python环境(我在练习的时候是用的Python3.6.8) 2.PyQt5安装 首先安装sip pip install sip 然后安装PyQt5-tools pip in ...

  3. MariaDB增删改

    1.MariaDB 数据类型 MariaDB数据类型可以分为数字,日期和时间以及字符串值. 使用数据类型的原则:够用就行, 尽量使用范围小的,而不用大的 常用的数据类型: 1.整数:int, bit( ...

  4. laravel 多字段登录

    protected function validateChinaPhoneNumber($number) { return preg_match('/^1[34578]\d{9}$/', $numbe ...

  5. 【MM系列】SAP 物料进销存报表查看

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]在SAP里查看数据的方法   前言部 ...

  6. database 学习

    ref : 什么是NoSQL,为什么要使用NoSQL?

  7. @Scheduled(cron = "0/5 * * * * *")将时间改为配置

    有两种方法:第一种当然你可以把Scheduled写到xml文件中进行配置. 第二种在你的类前面添加 此处讲解第二种写法 第二种在你的类前面添加@PropertySource("classpa ...

  8. 九、Zabbix-触发器

    1.触发器是用来触发报警,或这其他动作的机制,它需要依赖监控项,以监控项为基础创建 3.创建触发器 (1)配置—>模板—>需要调整的模板—>触发器 (2)编辑触发器

  9. 关于telnet的妙用

    1 使用telnet查看某个端口是否可以访问

  10. ESXi导出的CentOS7 ovf文件导入到workstation 无法打开GUI登录界面的问题解决方案

    1. 前几天将centos的机器导出为ovf 文件 然后使用 workstation 引入之后发现总是黑屏 然后有一个 横杠在闪 2. 解决办法是 修改centos的虚拟机配置文件,将显示器修改为这样 ...