Description
Input
Sample Input
输入1:
5
1 4 2 5 1
4
1 1 2 4
Output
Sample Output
输出1:
2
1 4
暴力加一点点小优化,没有拍结果错了QAQ
这一道题的暴力版本dp显然是枚举4个位置,然后转移,下面我们一个个找优化!
我们设4个位置分别为a[i],a[k],b[j],b[l](由(k,l)–>(i,j))
1:我们可以发现a[i]=b[j],a[k]=b[l]时才可能可以转移,所以我们先离散化一下,然后把值相等的都放到一个数组s中,数组里面记录这个值每一次出现的位置
2:我们可以发现如果有a[i]=a[i+1],或b[i]=b[i+1],那么我们可以合并这两个位置
3:我们可以把s数组中对每一种树位置的存储排一次序,然后把j从1->s[a[i],0]枚举一下,那么每一次j的值都会变大,那么我们存储每一次运算完之后的cy(cy表示最后一次转移方程l的位置),那么下一次做的时候l的位置就可以从cy开始了
到这里我们的dp已经是稳定 O(N3) ,大部分情况都是 O(N2) 的了!
那么怎么样的数据可以在这种情况下卡掉我们呢?
对于大部分a[i]<>a[i-1],b[i]<>b[i-1],而且离散化只有大概有500多个数
4:最后一个玄学优化!我们贪心的想,每次枚举k位置的时候,如果a[k]的值已经出现过了,那么肯定是选后面的更优,所以我们倒着枚举k的位置,并且用一个布尔数组判重就可以了
**事实证明,这个玄学算法水法很牛逼,而且卡不掉(而且比一些打的不好的正解还要快~)!
其实这个方法就是代码长了一点点
var
a,b,c,d:array[0..5005]of longint;
h:array[0..5005]of longint;
bz:array[0..5005]of boolean;
f,s,g,p:array[0..5005,0..5005]of longint;
i,j,k,l,n,m,x,y,ans,r,mid,cy:longint;
yjk:boolean;
procedure qsort(l,r:longint);
var
i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=c[(i+j) div 2];
repeat
while c[i]do inc(i);
while c[j]>mid do dec(j);
if i<=j then
begin
c[0]:=c[i];
c[i]:=c[j];
c[j]:=c[0];
inc(i);
dec(j);
end;
until i>j;
if ithen qsort(i,r);
if lthen qsort(l,j);
end;
function max(x,y:longint):longint;
begin
if xthen
begin
g[i,s[a[i],j]]:=k;
p[i,s[a[i],j]]:=s[a[k],l];
cy:=l;
exit(y);
end else exit(x);
end;
procedure qsort1(l,r,x:longint);
var
i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=s[x,(i+j) div 2];
repeat
while s[x,i]do inc(i);
while s[x,j]>mid do dec(j);
if i<=j then
begin
s[0,0]:=s[x,i];
s[x,i]:=s[x,j];
s[x,j]:=s[0,0];
inc(i);
dec(j);
end;
until i>j;
if ithen qsort1(i,r,x);
if lthen qsort1(l,j,x);
end;
procedure init;
begin
assign(input,'t2.in'); reset(input);
readln(n);
for i:=1 to n do read(a[i]);
readln;
readln(m);
for i:=1 to m do read(b[i]);
readln;
c:=a;
qsort(1,n);
l:=1;
h[1]:=c[1];
for i:=2 to n do
if c[i]<>c[i-1] then
begin
inc(l);
h[l]:=c[i];
end;
c:=h;
x:=0;
for i:=1 to n do
for j:=1 to l do
if c[j]=a[i] then
begin
a[i]:=j;
break;
end;
for i:=n downto 2 do
if a[i]=a[i-1] then
begin
for j:=i to n-1 do a[j]:=a[j+1];
inc(x);
end;
n:=n-x;
for i:=1 to m do
for j:=1 to l do
if b[i]=c[j] then
begin
b[i]:=j;
bz[i]:=true;
break;
end;
x:=0;
for i:=m downto 1 do
if bz[i]=false then
begin
for j:=i+1 to m do b[j-1]:=b[j];
inc(x);
end;
m:=m-x;
for i:=1 to m do
begin
inc(s[b[i],0]);
s[b[i],s[b[i],0]]:=i;
end;
end;
begin
init;
for i:=1 to l do qsort1(1,s[i,0],i);
s[0,0]:=1;
s[0,1]:=0;
mid:=l;
for i:=1 to n do
begin
fillchar(bz,sizeof(bz),false);
for k:=i-1 downto 0 do
if bz[a[k]]=false then
begin
bz[a[k]]:=true;
x:=1;
cy:=0;
if a[k]then
for j:=1 to s[a[i],0] do
begin
for l:=x to s[a[k],0] do
if s[a[i],j]>s[a[k],l] then
begin
f[i,s[a[i],j]]:=max(f[i,s[a[i],j]],f[k,s[a[k],l]]+1);
end else break;
x:=l;
l:=cy;
if l>0 then
f[i,s[a[i],j]]:=max(f[i,s[a[i],j]],f[k,s[a[k],l]]+1);
if f[i,s[a[i],j]]=mid then yjk:=true;
if yjk then break;
end;
if yjk then break;
end;
if yjk then break;
end;
for i:=n downto 1 do
for j:=1 to m do
if f[i,j]>ans then
begin
ans:=f[i,j];
x:=i;
y:=j;
end;
l:=0;
b:=h;
fillchar(h,sizeof(h),0);
while x>0 do
begin
inc(l);
h[l]:=x;
i:=g[x,y];
j:=p[x,y];
x:=i;
y:=j;
end;
writeln(ans);
for i:=l downto 1 do write(b[a[h[i]]],' ');
writeln;
close(input);
end.