Description
Input
Output
Sample Input
输入1:
5
1 4 2 5 1
4
1 1 2 4
输入2:
见共享
Sample Output
输出1:
2
1 4
输出2:
见共享
Data Constraint
题解
此题是一道奇妙的题目。
由于各种原因,本题开捆绑数据,我想原因是为了防止大家水分水特别高。
所以我比赛时爆零了
正解真的要大开脑洞才行。
首先当然想到的是DP
设f[i,j]表示前i个红色的船,当前选到第j个蓝色的船的最大答案。
设g[i,j]表示上述情况下时,上一个蓝色的船是什么。
这样就可以边转移边记录答案了。
转移方程——
f
[
i
,
j
]
:
=
m
a
x
(
f
[
i
−
1
,
k
]
+
1
)
;
g
[
i
,
j
]
:
=
k
;
[
a
[
i
]
=
b
[
j
]
]
f[i,j]:=max(f[i-1,k]+1);g[i,j]:=k;[a[i]=b[j]]
f[i,j]:=max(f[i−1,k]+1);g[i,j]:=k;[a[i]=b[j]]
f
[
i
,
j
]
:
=
f
[
i
−
1
,
j
]
;
g
[
i
,
j
]
:
=
j
;
[
a
[
i
]
<
>
b
[
j
]
]
f[i,j]:=f[i-1,j];g[i,j]:=j;[a[i]<>b[j]]
f[i,j]:=f[i−1,j];g[i,j]:=j;[a[i]<>b[j]]
这样能够拿到45分的好成绩。
那么考虑优化。
由于这个k我们看起来很烦,那么考虑把一些冗杂的状态给减去。
我们设h[i,j]表示当前a[i]=b[j]时的f[i,j]状态下,由h[i,j]转移过来。
可以把h[i,j]想象成一个最优的k。
那么,每次在做完f[i,j]后,用当前的h[i+1,j-1]转移到h[i+1,j]即可。
具体就是分两类讨论——
1、当b[j]<a[i+1]且f[i,h[n+1,j-1]]<f[i,j]时,就更新h[i+1,j]=j
2、否则就是h[i+1,j]=h[i+1,j-1]
好好理解就懂了。
代码
{$inline on}
var
i,j,k,l,n,m,ans,x,y,wz,gs,op,maxx,ni:longint;
a,b,bb,id,ad,bd:array[0..5000] of longint;
sum,map:array[1..5000,0..5000] of longint;
f,g,h:array[0..5000,0..5000] of longint;
answer:array[0..5000] of longint;
procedure qsort(l,r:longint);inline;
var
i,j,k,m:longint;
begin
i:=l;j:=r;
m:=b[(l+r) div 2];
repeat
while b[i]<m do inc(i);
while b[j]>m do dec(j);
if i<=j then
begin
k:=b[i];
b[i]:=b[j];
b[j]:=k;
k:=id[i];
id[i]:=id[j];
id[j]:=k;
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if r>i then qsort(i,r);
end;
function erfen(id,x,y:longint):longint;inline;
var
l,r,mid:longint;
begin
l:=x;
r:=y;
while l<r do
begin
mid:=(l+r)div 2;
if sum[id,x]=sum[id,mid] then l:=mid+1 else r:=mid;
end;
erfen:=l;
end;
begin
//assign(input,'qfd.in');reset(input);
//assign(input,'0data.in');reset(input);
readln(n);
for i:=1 to n do
begin
read(a[i]);
end;
readln(m);
for i:=1 to m do
begin
read(b[i]);
end;
for i:=1 to n do
begin
for j:=1 to m do
begin
if a[i]=b[j] then
begin
//for k:=0 to j-1 do
begin
if (b[h[i,j]]<b[j]) and (f[i,j]<f[i-1,h[i,j]]+1) then
begin
f[i,j]:=f[i-1,h[i,j]]+1;
g[i,j]:=h[i,j];
end;
end;
end
else
begin
f[i,j]:=f[i-1,j];
g[i,j]:=j;
end;
ni:=i+1;
if b[j]<a[ni] then
begin
if f[i,h[ni,j-1]]>=f[i,j] then
begin
h[ni,j]:=h[ni,j-1];
end
else
begin
h[ni,j]:=j;
end;
end
else
begin
h[ni,j]:=h[ni,j-1];
end;
end;
end;
for i:=1 to n do
begin
for j:=1 to m do
begin
if ans<f[i,j] then
begin
x:=i;
y:=j;
ans:=f[i,j];
end;
end;
end;
writeln(ans);
while x>0 do
begin
if a[x]=b[y] then
begin
inc(answer[0]);
answer[answer[0]]:=a[x];
end;
y:=g[x,y];
x:=x-1;
end;
for i:=answer[0] downto 1 do
begin
write(answer[i],' ');
end;
writeln;
end.