• 逆序对的相关问题:bzoj1831,bzoj2431


    先从简单一点的bzoj2431入手;

    n个数1~n已经限定了,所以

    对于1~i-1,新加入i,最多可以增加i-1个逆序对,最少增加0个逆序对

    f[i,j]表示1~i形成的序列逆序对为j的方案数

    比较容易得出f[i,j]=Σf[i-1,k];

    用前缀和优化即可

     1 const mo=10000;
     2 var f:array[0..1,0..1010] of longint;
     3     s:array[0..1010] of longint;
     4     i,j,k,n,m,p:longint;
     5 
     6 begin
     7   readln(n,m);
     8   k:=0;
     9   f[0,0]:=1;
    10   for i:=2 to n do
    11   begin
    12     k:=1-k;
    13     s[0]:=f[1-k,0] mod mo;
    14     for j:=1 to m do
    15     begin
    16       s[j]:=(s[j-1]+f[1-k,j]) mod mo;
    17       f[k,j]:=0;
    18     end;
    19     for j:=0 to m do
    20     begin
    21       p:=j-i+1;
    22       if p<0 then p:=0;
    23       f[k,j]:=(s[j]-s[p]+f[1-k,p]) mod mo;
    24     end;
    25   end;
    26   if f[k,m]<0 then f[k,m]:=f[k,m]+mo;
    27   writeln(f[k,m] mod mo);
    28 end.
    bzoj2431

    然后是bzoj1831

    首先我们可以先求出固定的逆序对;

    然后根据贪心的思想,不难得出需要填的数是不下降的

    具体证明见:http://www.cnblogs.com/htfy/archive/2012/12/11/2813497.html

    令big[i,j]表示第i为数字为j时,前面有多少个比它大的

    small[i,j]表示第i为数字为j时,前面有多少个比它小的

    f[i,j]表示第i个-1填j最小逆序对数目

    得:f[i,j]=min(f[i-1,k])+small[loc[i],j]+big[loc[i],j];

    我曾经讲过对于这样的dp怎么优化,具体见程序

     1 var c,a,b:array[0..10010] of longint;
     2     f,small,big:array[0..10010,0..110] of longint;
     3     t,n,m,i,j,ans,s:longint;
     4 
     5 function lowbit(x:longint):longint;
     6   begin
     7     exit(x and (-x));
     8   end;
     9 
    10 function ask(x:longint):longint;
    11   begin
    12     ask:=0;
    13     while x>0 do
    14     begin
    15       ask:=ask+c[x];
    16       x:=x-lowbit(x);
    17     end;
    18   end;
    19 
    20 procedure add(x:longint);
    21   begin
    22     while x<=m do
    23     begin
    24       inc(c[x]);
    25       x:=x+lowbit(x);
    26     end;
    27   end;
    28 
    29 begin
    30   readln(n,m);
    31   for i:=1 to n do
    32   begin
    33     read(a[i]);
    34     if a[i]=-1 then
    35     begin
    36       inc(t);
    37       b[t]:=i;
    38     end;
    39   end;
    40   for i:=n downto 1 do
    41   begin
    42     if a[i]<>-1 then
    43     begin
    44       add(a[i]);
    45       s:=s+ask(a[i]-1);
    46     end
    47     else begin
    48       for j:=1 to m do
    49         small[i,j]:=ask(j-1);
    50     end;
    51   end;
    52   fillchar(c,sizeof(c),0);
    53   for i:=1 to n do
    54   begin
    55     if a[i]<>-1 then add(a[i])
    56     else begin
    57       for j:=1 to m do
    58         big[i,j]:=ask(m)-ask(j);
    59     end;
    60   end;
    61   for i:=1 to t do
    62   begin
    63     f[i,1]:=f[i-1,1];
    64     for j:=2 to m do
    65       f[i,j]:=min(f[i-1,j],f[i,j-1]);   //优化
    66     for j:=1 to m do
    67       f[i,j]:=f[i,j]+big[b[i],j]+small[b[i],j];
    68   end;
    69   ans:=2147483647;
    70   for i:=1 to m do
    71     ans:=min(ans,f[t,i]);
    72   writeln(ans+s);
    73 end.
    bzoj1831

    总体来说,这两题不算太难,但我还是花了很多时间

    1. 是做题不够认真,戒之戒之

    2. 自己想出的零散的特点性质没有很好的整合,导致题目做不出来

  • 相关阅读:
    [收藏]成大事必备9种能力9种手段9种心态
    招聘第一位网站编辑
    买了两本书
    并行计算Brahma :LINQtoGPU
    PostSharp 1.0 RTM发布了
    .NET StockTrader 2.0 新版本
    Windows Communication Foundation FAQ
    SQL Server 2008基于策略的管理
    WCF 性能基准报告
    ADO.NET实体框架连接串引发的异常:Unable to load the specified metadata resource
  • 原文地址:https://www.cnblogs.com/phile/p/4473246.html
Copyright © 2020-2023  润新知