bzoj1264

表面上看这是一道LCS问题

LCS问题O(n2)的复杂度已经很优秀了

而这道题需要O(nlogn)以下的复杂度才能AC

所以我们要找经典问题的特殊性

特殊就在这两个串中,每个数字都是恰好出现5次

不难想到先预处理每个数在B串依次出现的位置

先扫一遍A串,对于每一个数a[i],设f[j]=LCS(i,j)

显然这个数在B串出现的位置才会更新答案

对于每个出现的位置x1~x5,显然f[x]=max(f[w])+1 (1<=w<=x-1);

为了避免重复更新,我们要从后往前更新f[x]

再考虑怎么快速找到最大值,显然这里要找的是前缀中的最大值

不难想到,我们可以通过树状数组维护

 1 var b,f,a,c:array[0..100010] of longint;
 2     w:array[0..100010,0..5] of longint;
 3     j,n,i,x,ans:longint;
 4 
 5 function max(a,b:longint):longint;
 6   begin
 7     if a>b then exit(a) else exit(b);
 8   end;
 9 
10 function lowbit(x:longint):longint;
11   begin
12     exit(x and (-x));
13   end;
14 
15 function get(x:longint):longint;
16   begin
17     get:=0;
18     while x>0 do
19     begin
20       get:=max(get,c[x]);
21       x:=x-lowbit(x);
22     end;
23   end;
24 
25 procedure update(x,p:longint);
26   begin
27     while x<=5*n do
28     begin
29       c[x]:=max(c[x],p);
30       x:=x+lowbit(x);
31     end;
32   end;
33 
34 begin
35   readln(n);
36   for i:=1 to 5*n do
37     read(a[i]);
38   for i:=1 to 5*n do
39   begin
40     read(x);
41     inc(b[x]);
42     w[x,b[x]]:=i;
43   end;
44   for i:=1 to 5*n do
45   begin
46     for j:=5 downto 1 do
47     begin
48       x:=w[a[i],j];
49       f[x]:=get(x-1)+1;
50       update(x,f[x]);
51     end;
52   end;
53   for i:=1 to 5*n do
54     ans:=max(f[i],ans);
55   writeln(ans);
56 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473165.html