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回到公司。
输出一行一个整数,表示上锁时间总和的最大值。
4 20 2
3 11
5 15
6 10
12 18
13
【HINT】
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,总计13时段,故答案为13。
对于100%的数据:
1<=N<=2000
1<=M<=10^9
对于任意i,j (1<=i<=N,1<=j<=N,i≠j),Si≠Sj,Si≠Tj,Ti≠Tj
我说的区间就为这个区间的间隔时间,即答案求的东西。
首先,按照时刻排序,然后可以发现:连续两个人的进出状态需要满足谁有钥匙使得这个区间能否加入到答案里
1、先进后出:不需要钥匙
2、先进后进:后面的有钥匙
3、先出后进:两个人都要钥匙
4、先出后出:前面的人有钥匙
知道这些之后就可以打爆搜了,20分。
观察一下每种状态,发现如果是第一种,可以直接将这个区间加入答案。对于第二种,把区间加入后面那个人的权值。对于第四种,把区间加入前面那个人的权值。
第三种,从进的人向出的人连一条权值为这个区间的边。
问题变成了,选择一个点,就可以获得这个点的权值,如果一个点与这个点的父亲同时被选,可以获得额外权值。目标为使权值最大。
观察一下连边,会发现所有连边最后形成若干个链(自己想为什么)。把这些链的链头和链尾依次连边,边的权值为0,最后就会形成一条大链。如果两个点一开始在不同的链,合成大链后,这两个点即使一个是另一个的父亲,它们同时选,也不可能可以获得额外权值。所以将小链合并的连边权值为0。把一个点也当成一个链连到一起。
如果一个点自己给自己连边,把这个边的权值加入到这个点的权值就行了。不能自己连自己。
解答这个问题,DP。F[i,j]表示前i个点选了j个,并且选第i个的最大值。
f[i][j]=max(max(f[1~i-2][j-1]),f[i-1][j-1]+边权)+点权。
max(f[1~i-2][j-1])可以边做边求,不需要再枚举。
时间复杂度O(nk)。
var
n,m,k,x,y,i,j,ans,anss:longint;
a:array[1..4100,1..3] of longint;
b,g:array[0..2100] of longint;
f:array[0..2100,0..2100] of longint;
lb:array[0..2100,1..3] of longint;
bz:array[1..2100] of boolean;
function max(a,b:longint):longint;begin if a>b then exit(a)else exit(b);end;
procedure px(i,j:longint);
var l,r,m:longint;
t:array[1..3] of longint;
begin
l:=i;r:=j;m:=a[(i+j)div 2,1];
repeat
while a[i,1]<m do inc(i);while a[j,1]>m do dec(j);
if i<=j then
begin
t:=a[i];a[i]:=a[j];a[j]:=t;
inc(i);dec(j);
end;
until i>j;
if l<j then px(l,j);
if i<r then px(i,r);
end;
function doit:longint;
var
i,j:longint;
begin
j:=a[1,1]+m-a[n*2,1];
for i:=1 to n*2-1 do
begin
if (a[i+1,3]=1) then
begin
if a[i,3]=1 then
begin
inc(b[a[i,2]],a[i+1,1]-a[i,1]);
end
else
begin
j:=j+a[i+1,1]-a[i,1];
end;
end
else
begin
if a[i,3]=1 then
begin
if a[i,2]=a[i+1,2] then
begin
inc(b[a[i,2]],a[i+1,1]-a[i,1]);
continue;
end;
lb[a[i+1,2],1]:=a[i,2];
lb[a[i+1,2],2]:=a[i+1,1]-a[i,1];
lb[a[i,2],3]:=a[i+1,2];
end
else
begin
inc(b[a[i+1,2]],a[i+1,1]-a[i,1]);
end;
end;
end;
exit(j);
end;
function dfs(x:longint):longint;
begin
bz[x]:=true;
if lb[x,1]<>0 then exit(dfs(lb[x,1]));
exit(x);
end;
procedure dg(x_,x,j:longint);
begin
if x=0 then exit;
if j=1 then f[x,1]:=b[x]
else f[x,j]:=max(f[x,j],max(g[j],f[x_,j-1]+lb[x_,2])+b[x]);
ans:=max(ans,f[x,j]+anss);
g[j]:=max(g[j],f[x_,j-1]);
dg(x,lb[x,1],j);
end;
begin
assign(input,'key.in'); reset(input);
assign(output,'key.out'); rewrite(output);
read(n,m,k);
for i:=1 to n do
begin
read(x,y);
a[i*2-1,1]:=x;a[i*2-1,2]:=i;a[i*2-1,3]:=1;
a[i*2,1]:=y;a[i*2,2]:=i;a[i*2,3]:=2;
end;
px(1,n*2);x:=0;
anss:=doit;
for i:=1 to n do
begin
if (lb[i,3]=0)and(bz[i]=false) then
begin
if x=0 then x:=i;
lb[j,1]:=i;lb[j,2]:=0;
j:=dfs(i);
end;
end;
for j:=1 to k do
begin
dg(0,x,j);
end;
writeln(ans);
close(input);close(output);
end.