一些动规题

来源:互联网 发布:白帽优化 编辑:程序博客网 时间:2024/06/06 02:15

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<<1end;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]:=yend;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 endend;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 endend;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 endend;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; oufend.

在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 endend;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) endend;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  endend;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 endend;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; oufend.