【NOIP2015模拟11.3】备用钥匙
题目
你知道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】备用钥匙的更多相关文章
- JZOJ 4298. 【NOIP2015模拟11.2晚】我的天
4298. [NOIP2015模拟11.2晚]我的天 (File IO): input:ohmygod.in output:ohmygod.out Time Limits: 1000 ms Memor ...
- 【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\)个元素的 ...
- 【NOIP2015模拟11.5】JZOJ8月5日提高组T1 俄罗斯套娃
[NOIP2015模拟11.5]JZOJ8月5日提高组T1 俄罗斯套娃 题目 题解 题意就是说 将1~\(n\)排列,问有多少种方案使得序列的逆序对个数小于\(k\) 很容易想到DP 设\(f[i][ ...
- 【NOIP2015模拟11.2晚】JZOJ8月4日提高组T2 我的天
[NOIP2015模拟11.2晚]JZOJ8月4日提高组T2 我的天 题目 很久很以前,有一个古老的村庄--xiba村,村子里生活着n+1个村民,但由于历届村长恐怖而且黑暗的魔法统治下,村民们各自过着 ...
- 【NOIP2015模拟11.4】JZOJ2020年8月6日提高组T2 最优交换
[NOIP2015模拟11.4]JZOJ2020年8月6日提高组T2 最优交换 题目 题解 题意 有一个长度为\(n\)的正整数 最多可以进行\(k\)次操作 每次操作交换相邻两个位置上的数 问可以得 ...
- 【NOIP2015模拟11.4】JZOJ8月6日提高组T1 刷题计划
[NOIP2015模拟11.4]JZOJ8月6日提高组T1 刷题计划 题目 题解 题意 有\(n\)道题,编号为1~\(n\) 给出\(m\)次操作 每次操作有3种类型 1 \(x\) 表示交了\(A ...
- 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行
[NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...
- JZOJ4307. 【NOIP2015模拟11.3晚】喝喝喝
Description
- [JZOJ 4307] [NOIP2015模拟11.3晚] 喝喝喝 解题报告
题目链接: http://172.16.0.132/senior/#main/show/4307 题目: 解题报告: 题目询问我们没出现坏对的连续区间个数 我们考虑从左到有枚举右端点$r$,判断$a[ ...
随机推荐
- Java多线程学习——join方法的使用
join在线程里面意味着“插队”,哪个线程调用join代表哪个线程插队先执行——但是插谁的队是有讲究了,不是说你可以插到队头去做第一个吃螃蟹的人,而是插到在当前运行线程的前面,比如系统目前运行线程A, ...
- 求方程x1+x2+x3=15的整数解的数目
求方程x1+x2+x3=15的整数解的数目要求0≤x1≤5,0≤x2≤6,0≤x3≤7.解:令N为全体非负整数解(x1,x2,x3),A1为其中x1≥6的解:y1=x1-6≥0的解:A2为其中x2≥7 ...
- linux 通配符与正则表达式
linux通配符和三剑客(grep.awk.sed)正则表达式是不一样的 通配符一般用户命令行bash环境,而linux正则表达式用于awk.grep.sed
- sprintf()函数可能发生的错误
接收到如下数据: GET http://app.tdvpn.com/heartbeat?mac=898607B81017AT+CIPSTATUS? &status=/ HTTP/1.1 Hos ...
- (三)认识twisted reactor
一.reactor是单线程模型,简单粗暴,也就是说网络IO和我们的业务逻辑一般是在一个线程里,其中网络IO通过event loop的方式去异步执行,效率也很高.看下官网的这幅图,比较清晰 twiste ...
- Monkey常用命令详解
使用monkey help 命令查看命令参数,如下: C:\Users\chenfenping>adb shell monkey -help usage: monkey [-p ALLOWED_ ...
- HDU 1043 Eight 八数码问题 A*算法(经典问题)
HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...
- Fedora添加软件桌面快捷方式
以下以添加Eclipse为例 在桌面上新建Eclipse.desktop 文件,向其写入如下代码 [Desktop Entry] Name=Eclipse Comment=用Eclipse开发 Exe ...
- 最长公共子序列(LCS) Medium2
The company "21st Century Fruits" has specialized in creating new sorts of fruits by trans ...
- 手写spring事务框架, 揭秘AOP实现原理。
AOP面向切面编程:主要是通过切面类来提高代码的复用,降低业务代码的耦合性,从而提高开发效率.主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等. AOP实现原理:aop是通过cgli ...