题面
题意描述(有点长, 请耐心阅读)
你知道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社的社长很重视时间效率,因此每个员工在离开或回到公司的时刻以外,不允许开锁或者上锁。
出于安全的考虑,社长希望上锁的时间越长越好。现在他将员工出入公司的信息和准备交给员工的钥匙数量告诉了你,请你求出在能使所有员工回到公司的时候都能进入公司的大门的前提下,上锁的时间最长是多少。
输入输出格式
输入格式
第一行三个空格分隔的整数N,M,K,表示JOI社的员工有N个,工作时间从时刻0到时刻M,备用钥匙有K把。 接下来N行,第i行(1<=i<=N)有两个空格分隔的整数Si,Ti,表示员工i在时刻Si离开公司,时刻Ti回到公司。
输出格式
输出一行一个正整数,表示上锁时间总和的最大值。
样例数据
输入数据 1
4 20 2
3 11
5 15
6 10
12 18
输出数据 1
13
提示&样例解释
JOI社共有4名员工,工作时间为时刻0~时刻M,共有两把备用钥匙。 将钥匙交予员工2和员工4,一天日程如下:
时刻0,锁是关闭状态
时刻3,员工1离开公司。由于员工1没有备用钥匙,无法锁门。
时刻5,员工2离开公司,锁门。
时刻6,员工3离开公司。由于员工3没有备用钥匙,无法锁门。
时刻10,员工3回到公司,不锁门。
时刻11,员工1回到公司,锁门。
时刻12,员工4离开公司,锁门。
时刻15,员工2回到公司,锁门。
时刻18,员工4回到公司,锁门。
直到时刻20为止,锁都保持关闭状态。上锁的时间段为0~3,5~6,11~20,总计 ( 3 − 0 ) + ( 6 − 5 ) + ( 20 − 11 ) (3-0)+(6-5)+(20-11) (3−0)+(6−5)+(20−11)时段,故答案为13。
数据范围
对于100%的数据:
1
≤
N
≤
2000
,
∣
∣
1
≤
M
≤
1
0
9
,
∣
∣
1
≤
k
<
N
,
∣
∣
1
≤
S
i
<
T
i
<
M
1\le N\le 2000,||1\le M\le 10^9,||1\le k<N,||1\le S_i<T_i<M
1≤N≤2000,∣∣1≤M≤109,∣∣1≤k<N,∣∣1≤Si<Ti<M
题解
思路
我们把所有员工的进出时间, 记录在一个数轴上, 每次某个人的出
/
/
/入操作作为一个点
如下图:
对于每一个区间(最小区间, 区间内除端点外不含其他点) 的两个端点, 一共有四种情况
- 左入右入
- 左入右出
- 左出右入
- 左出右出
现在我们在不考虑其他区间状态 \;\; (或者说假设其他区间门都是开着的) \;\; 的情况下, 假设当前区间门一直都是上锁的, 需要钥匙的情况
- 左入右入
第一个人进来的时候, 由于门的状态不确定, 所以不一定需要钥匙
第二个人进来的时候, 根据假设, 门一定是锁着的, 所以它一定需要钥匙 - 左入右出
第一个人进来的时候, 由于门的状态不确定, 所以不一定需要钥匙
第二个人出去的时候, 门可以从内部解锁, 所以它不一定需要钥匙 - 左出右入
第一个人出去的时候, 根据假设, 一定需要从外面锁门, 所以一定需要钥匙
第二个人进来的时候, 门一定是锁着的, 所以它也一定需要钥匙 - 左出右出
第一个人出去的时候, 根据假设, 一定需要从外面锁门, 所以一定需要钥匙
第二个人出去的时候, 门可以在内部解锁, 所以它不一定需要钥匙
现在设这段区间长度为 t i m e time time, 我们发现,
对于 2 2 2情况, 这段区间的贡献是一定成立的, 无论这个区间的前后区间是打开的还是锁上的 (请自行枚举证明)
对于 1 , 4 1,4 1,4情况, 这段区间能否产生贡献 (能否一直上锁) 只依赖于其中的一个人 (就是一定要拿钥匙的那个人) . 因此我们把这一段的贡献加到这个人身上 (点权)
对于 3 3 3情况, 这段区间能否产生贡献同时依赖于两个人 (必须两个人同时拿着钥匙才能有贡献) , 因此我们把这两个人连边, 并且单开一个数组 e d g e [ i ] edge[i] edge[i], 表示这两个点所代表的两个人同时拥有钥匙时产生的贡献 (边权)
对于一种特殊情况, 左右端点代表同一个人, 我们就把贡献加到这个人身上 (点权)
这样"加工"完后, 我们发现, 由于每一个人最多被连了两给边(它的出
/
/
/入都作为某个
3
3
3情况的出
/
/
/入), 最后的图一定是由若干条链组成的 (请自行枚举证明).
我们把这些链拼在一起 (链和链之间边权为
0
0
0), 重新编号, 就变成了下面的题目
现在有 n n n个点, n − 1 n-1 n−1条边, 满足给的图时一个链, 每个点有权值 a i a_i ai, 在其中选取 k k k个点, 如果选取了相临的两个点, 就回额外产生贡献 e d g e i edge_i edgei, 求产生贡献的最大值
现在就可以
d
p
dp
dp了
定义一个方程式
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示现在枚举到了第
i
i
i个点, 且在
i
i
i点使用钥匙, 已经用了
j
j
j把钥匙, 产生贡献的最大值
转移还是很好想的
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
k
]
[
j
−
1
]
,
d
p
[
i
−
1
]
[
j
−
1
]
+
e
d
g
e
i
−
1
)
+
a
[
i
]
(
1
≤
k
≤
i
−
2
)
dp[i][j]=max(dp[k][j-1],\;dp[i-1][j-1]+edge_{i-1})+a[i](1\le k\le i-2)
dp[i][j]=max(dp[k][j−1],dp[i−1][j−1]+edgei−1)+a[i](1≤k≤i−2)
但是, 这样转移会
T
L
E
TLE
TLE, 原因就是枚举
k
k
k, 求其最大值的过程过慢
我们可以额外记录一个数组
g
[
i
]
[
j
]
g[i][j]
g[i][j], 表示
f
[
1
]
[
j
]
f[1][j]
f[1][j]到
f
[
i
]
[
j
]
f[i][j]
f[i][j]的最大值
最后的时间复杂度为
O
(
n
k
)
O(nk)
O(nk)
完美
!
完美!
完美!
AC Code
先欠着, 明天再给