ps:代码有点丑。
二维偏序的最长上升子序列
看到标题是不是觉得很水呢。。。
但是如果其中一维是dfs序,即在树上呢。。。
而且,还得缩环成树。。。
先缩环,一维dfs,二维线段树or单调栈。
{$M 100000000}
uses math;
var t,b,rt,w,tail,tail1,v,q,p,st,f:array[1..300000]of longint;
d:array[1..524288]of longint;
v1:array[1..200000]of boolean;
next,next1,sora,sora1:array[1..500000]of longint;
ans,s1,sta,m1,ss,ss1,n,r:longint;
procedure inf;
begin
assign(input,'travel.in');reset(input);
assign(output,'travel.out');rewrite(output)
end;
procedure ouf;
begin
close(input);close(output)
end;
procedure origin;
var i:longint;
begin
for i:=1 to n do tail[i]:=i;ss:=n;
for i:=1 to n do tail1[i]:=i;ss1:=n;
m1:=1;
while m1<=n+2 do m1:=m1<<1
end;
procedure qsort(l,r:longint);
var i,j,x,c:longint;
begin
i:=l;j:=r;x:=w[(l+r)>>1];
repeat
while w[i]<x do inc(i);
while x<w[j] do dec(j);
if not(i>j) then begin
c:=w[i];w[i]:=w[j];w[j]:=c;
c:=p[i];p[i]:=p[j];p[j]:=c;
inc(i);dec(j)
end
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j)
end;
procedure qsort2(l,r:longint);
var i,j,x,c:longint;
begin
i:=l;j:=r;x:=q[st[(l+r)>>1]];
repeat
while q[st[i]]<x do inc(i);
while x<q[st[j]] do dec(j);
if not(i>j) then begin
c:=st[i];st[i]:=st[j];st[j]:=c;
inc(i);dec(j)
end
until i>j;
if i<r then qsort2(i,r);
if l<j then qsort2(l,j)
end;
procedure link(x,y:longint);
begin
inc(ss);next[tail[x]]:=ss;tail[x]:=ss;sora[ss]:=y
end;
procedure link2(x,y:longint);
begin
inc(ss1);next1[tail1[x]]:=ss1;tail1[x]:=ss1;sora1[ss1]:=y;
next[tail[x]]:=next[y];tail[x]:=tail[y]
end;
procedure dfs2(x:longint);
var rr,i:longint;
begin
v[x]:=1;
inc(r);st[r]:=x;
if v[rt[x]]=2 then begin dec(r);v[x]:=2;exit end;
if v[rt[x]]=0 then begin
dfs2(rt[x]);
if sta=0 then dec(r)
else if sta=x then begin
inc(s1);b[x]:=s1;v1[x]:=true;
rr:=r;
while st[r]<>x do dec(r);
for i:=r+1 to rr do begin
b[st[i]]:=s1;
link2(x,st[i])
end;
dec(r)
end;
v[x]:=2;
exit
end;
if v[rt[x]]=1 then begin
sta:=rt[x];
// dec(r);
v[x]:=2
end;
end;
function ask(l,r:longint):longint;
begin
if l>r then exit(0);
l:=l+m1-1;r:=r+m1+1;ask:=0;
while not(l xor r=1) do begin
if l and 1=0 then ask:=max(ask,d[l+1]);
if r and 1=1 then ask:=max(ask,d[r-1]);
l:=l>>1;r:=r>>1
end
end;
procedure change(x,w:longint);
begin
x:=x+m1;d[x]:=w;
x:=x>>1;
while x<>0 do begin
d[x]:=max(d[x<<1],d[x<<1+1]);
x:=x>>1
end
end;
procedure dfs(x:longint);
var i,ne:longint;
begin
if not v1[x] then begin
f[x]:=ask(1,q[x]-1)+1;
change(t[x],f[x]);
end;
i:=x;
while i<>0 do begin
i:=next[i];ne:=sora[i];
if b[ne]=0 then dfs(ne)
end;
change(t[x],0)
end;
procedure doit(x:longint);
var sum,tot,i,ne:longint;
begin
fillchar(d,sizeof(d),0);
r:=1;st[r]:=x;
i:=x;
while next1[i]<>0 do begin
i:=next1[i];ne:=sora1[i];
inc(r);st[r]:=ne
end;
qsort2(1,r);
sum:=0;tot:=0;
for i:=1 to r do begin
ne:=st[i];
if q[ne]<>q[st[i-1]] then begin
sum:=sum+tot;
f[ne]:=sum+1;change(t[ne],f[ne]);
tot:=1
end
else begin
f[ne]:=sum+1;change(t[ne],f[ne]);
inc(tot)
end
end
end;
procedure init;
var i,x:longint;
begin
readln(n);
origin;
for i:=1 to n do begin
read(w[i]);
p[i]:=i
end;
qsort(1,n);
for i:=1 to n do begin
if w[i]<>w[i-1] then q[p[i]]:=i
else q[p[i]]:=q[p[i-1]];
t[p[i]]:=i
end;
for i:=1 to n do begin
read(x);
rt[i]:=x;
link(x,i)
end;
fillchar(v,sizeof(v),0);fillchar(st,sizeof(st),0);
fillchar(b,sizeof(b),0);s1:=0;
fillchar(v1,sizeof(v1),false);
for i:=1 to n do
if v[i]=0 then begin
r:=0;sta:=0;
dfs2(i)
end;
for i:=1 to n do
if (v1[i])or(rt[i]=i) then begin
if rt[i]<>i then doit(i) else begin change(t[i],1);b[i]:=i end;
dfs(i)
end;
ans:=0;
for i:=1 to n do ans:=max(ans,f[i]);
writeln(ans)
end;
begin
inf;
init;
ouf
end.
在n*m的图上,求一个点数为k的联通块,每个格子有一个权值。使得这些格子的任意 2 个,都可仅通过上、下、左、右中的两种方向互达,并使权值最大。
丑丑的dp,f[i,l,r,k]表示到第i行,第i行左端点为l,右端点为r,有k个格子的最大值。分成4种转移方程后,互相转。写得很想吐。我还把l,r状压在一起。
uses math;
const ss:array[1..120]of longint=
(1,2,3,4,6,7,8,12,14,15,
16,24,28,30,31,32,48,56,60,62,
63,64,96,112,120,124,126,127,128,192,
224,240,248,252,254,255,256,384,448,480,
496,504,508,510,511,512,768,896,960,992,
1008,1016,1020,1022,1023,1024,1536,1792,1920,1984,
2016,2032,2040,2044,2046,2047,2048,3072,3584,3840,
3968,4032,4064,4080,4088,4092,4094,4095,4096,6144,
7168,7680,7936,8064,8128,8160,8176,8184,8188,8190,
8191,8192,12288,14336,15360,15872,16128,16256,16320,16352,
16368,16376,16380,16382,16383,16384,24576,28672,30720,31744,
32256,32512,32640,32704,32736,32752,32760,32764,32766,32767);
kk:array[1..120]of longint=
(1,1,2,1,2,3,1,2,3,4,
1,2,3,4,5,1,2,3,4,5,
6,1,2,3,4,5,6,7,1,2,
3,4,5,6,7,8,1,2,3,4,
5,6,7,8,9,1,2,3,4,5,
6,7,8,9,10,1,2,3,4,5,
6,7,8,9,10,11,1,2,3,4,
5,6,7,8,9,10,11,12,1,2,
3,4,5,6,7,8,9,10,11,12,
13,1,2,3,4,5,6,7,8,9,
10,11,12,13,14,1,2,3,4,5,
6,7,8,9,10,11,12,13,14,15);
var f,g,e:array[1..4,1..15,1..120,1..225]of longint;
a:array[1..15,1..15]of longint;
c:array[1..15,1..120]of longint;
t,t2,t3,t4:array[1..120,1..120]of boolean;
anso,ansi,ansj,ans,n,m,k,maxs,k1,k2:longint;
b:array[0..15]of longint;
procedure inf;
begin
assign(input,'Bigagrib.in');reset(input);
assign(output,'Bigagrib.out');rewrite(output)
end;
procedure ouf;
begin
close(input);close(output)
end;
function check1(s,ns:longint):boolean;
var a,b:array[0..15]of longint;
k,k1:longint;
begin
if s and ns=0 then exit(false);
fillchar(a,sizeof(a),0);fillchar(b,sizeof(b),0);
k:=s;
while k<>0 do begin
inc(a[0]);a[a[0]]:=k and 1;
k:=k>>1
end;
k:=ns;
while k<>0 do begin
inc(b[0]);b[b[0]]:=k and 1;
k:=k>>1
end;
if a[0]<b[0] then exit(false);
for k:=1 to a[0] do
if a[k]=1 then break;
for k1:=1 to b[0] do
if b[k1]=1 then break;
if b[k]=1 then exit(true)
else exit(false)
end;
function check2(s,ns:longint):boolean;
var a,b:array[0..15]of longint;
k,k1:longint;
begin
if s and ns=0 then exit(false);
fillchar(a,sizeof(a),0);fillchar(b,sizeof(b),0);
k:=s;
while k<>0 do begin
inc(a[0]);a[a[0]]:=k and 1;
k:=k>>1
end;
k:=ns;
while k<>0 do begin
inc(b[0]);b[b[0]]:=k and 1;
k:=k>>1
end;
if a[0]<b[0] then exit(false);
for k:=1 to a[0] do
if a[k]=1 then break;
for k1:=1 to b[0] do
if b[k1]=1 then break;
if k<=k1 then exit(true)
else exit(false)
end;
function check3(s,ns:longint):boolean;
var a,b:array[0..15]of longint;
k,k1:longint;
begin
if s and ns=0 then exit(false);
fillchar(a,sizeof(a),0);fillchar(b,sizeof(b),0);
k:=s;
while k<>0 do begin
inc(a[0]);a[a[0]]:=k and 1;
k:=k>>1
end;
k:=ns;
while k<>0 do begin
inc(b[0]);b[b[0]]:=k and 1;
k:=k>>1
end;
if a[0]>b[0] then exit(false);
for k:=1 to a[0] do
if a[k]=1 then break;
for k1:=1 to b[0] do
if b[k1]=1 then break;
if k1<k then exit(false);
if b[a[0]]=1 then exit(true)
else exit(false)
end;
function check4(s,ns:longint ): boolean;
var a,b:array[0..15]of longint;
k,k1:longint;
begin
if s and ns=0 then exit(false);
fillchar(a,sizeof(a),0);fillchar(b,sizeof(b),0);
k:=s;
while k<>0 do begin
inc(a[0]);a[a[0]]:=k and 1;
k:=k>>1
end;
k:=ns;
while k<>0 do begin
inc(b[0]);b[b[0]]:=k and 1;
k:=k>>1
end;
if a[0]>b[0] then exit(false);
for k:=1 to a[0] do
if a[k]=1 then break;
for k1:=1 to b[0] do
if b[k1]=1 then break;
if k>=k1 then exit(true)
else exit(false)
end;
procedure origin;
var s,ns,i,j,p,x:longint;
begin
for i:=1 to n do
for j:=1 to maxs do
if kk[j]<=k then begin
p:=m;x:=ss[j];
while x<>0 do begin
c[i,j]:=c[i,j]+a[i,p]*(x and 1);
x:=x>>1;dec(p)
end;
f[1,i,j,kk[j]]:=c[i,j];f[2,i,j,kk[j]]:=c[i,j];
f[3,i,j,kk[j]]:=c[i,j];f[4,i,j,kk[j]]:=c[i,j]
end;
for i:=1 to maxs do begin
if kk[i]<=k then
for j:=1 to maxs do
if kk[j]<=k then begin
s:=ss[i];ns:=ss[j];
if s<>ns then t[i,j]:=check1(s,ns) else t[i,j]:=true;
// *****
// ****
if s<>ns then t2[i,j]:=check2(s,ns) else t2[i,j]:=true;
// ******
// ***
if s<>ns then t3[i,j]:=check3(s,ns) else t3[i,j]:=true;
// *****
// *****
if s<>ns then t4[i,j]:=check4(s,ns) else t4[i,j]:=true
// ***
// ******
end
end
end;
procedure dfs(o,i,j,k:longint);
begin
if k=0 then exit;
dfs(g[o,i,j,k],i-1,e[o,i,j,k],k-kk[j]);
fillchar(b,sizeof(b),0);
k1:=ss[j];
while k1<>0 do begin
inc(b[0]);b[b[0]]:=k1 and 1;
k1:=k1>>1
end;
for k1:=1 to b[0] do
if b[k1]=1 then break;
for k2:=b[0] downto k1 do begin
writeln(i,' ',m-k2+1)
end
end;
procedure getout;
var i,j:longint;
begin
anso:=0;ansi:=0;ansj:=0;
for i:=1 to n do
for j:=1 to maxs do begin
if f[1,i,j,k]>ans then begin
ans:=f[1,i,j,k];
anso:=1;ansi:=i;ansj:=j
end;
if f[2,i,j,k]>ans then begin
ans:=f[2,i,j,k];
anso:=2;ansi:=i;ansj:=j
end;
if f[3,i,j,k]>ans then begin
ans:=f[3,i,j,k];
anso:=3;ansi:=i;ansj:=j
end;
if f[4,i,j,k]>ans then begin
ans:=f[4,i,j,k];
anso:=4;ansi:=i;ansj:=j
end
end
end;
procedure updata(o1,o2,i,j,p,i1,j1,p1:longint);
begin
if p1>k then exit;
if f[o1,i,j,p]+c[i1,j1]>f[o2,i1,j1,p1] then begin
f[o2,i1,j1,p1]:=f[o1,i,j,p]+c[i1,j1];
g[o2,i1,j1,p1]:=o1;
e[o2,i1,j1,p1]:=j
end
end;
procedure init;
var i,j,p,nj:longint;
begin
readln(n,m,k);
for i:=1 to n do begin
for j:=1 to m do read(a[i,j]);
readln
end;
fillchar(t,sizeof(t),false);fillchar(t2,sizeof(t2),false);fillchar(t3,sizeof(t3),false);fillchar(t4,sizeof(t4),false);
fillchar(c,sizeof(c),0);
fillchar(f,sizeof(f),0);
maxs:=1<<m-1;
for i:=1 to 120 do
if ss[i]=maxs then break;
maxs:=i;
origin;
for i:=1 to n-1 do
for j:=1 to maxs do
for p:=kk[j] to k do
for nj:=1 to maxs do begin
if f[1,i,j,p]<>0 then begin
if t[j,nj] then updata(1,1,i,j,p,i+1,nj,p+kk[nj]);
if t2[j,nj] then updata(1,2,i,j,p,i+1,nj,p+kk[nj])
end;
if f[2,i,j,p]<>0 then begin
if t2[j,nj] then updata(2,2,i,j,p,i+1,nj,p+kk[nj])
end;
if f[3,i,j,p]<>0 then begin
if t2[j,nj] then updata(3,2,i,j,p,i+1,nj,p+kk[nj]);
if t3[j,nj] then updata(3,3,i,j,p,i+1,nj,p+kk[nj])
end;
if f[4,i,j,p]<>0 then begin
if t[j,nj] then updata(4,1,i,j,p,i+1,nj,p+kk[nj]);
if t2[j,nj] then updata(4,2,i,j,p,i+1,nj,p+kk[nj]);
if t3[j,nj] then updata(4,3,i,j,p,i+1,nj,p+kk[nj]);
if t4[j,nj] then updata(4,4,i,j,p,i+1,nj,p+kk[nj]);
end
end;
ans:=0;
getout;
writeln(ans);
dfs(anso,ansi,ansj,k)
end;
begin
inf;
init;
ouf
end.