zoukankan      html  css  js  c++  java
  • BZOJ1831: [AHOI2008]逆序对

    1831: [AHOI2008]逆序对

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 341  Solved: 226
    [Submit][Status]

    Description

    小可可和小卡卡想到Y岛上旅游,但是他们不知道Y岛有多远。好在,他们找到一本古老的书,上面是这样说的: 下面是N个正整数,每个都在1~K之间。如果有两个数A和B,A在B左边且A大于B,我们就称这两个数为一个“逆序对”。你数一数下面的数字里有多少个逆序对,你就知道Y岛离这里的距离是多少千米了。 比如说,4 2 1 3 3里面包含了5个逆序对:(4, 2), (4, 1), (4, 3), (4, 3), (2, 1)。 可惜的是,由于年代久远,这些数字里有一部分已经模糊不清了,为了方便记录,小可可用“-1”表示它们。比如说,4 2 -1 -1 3 可能原来是4 2 1 3 3,也可能是4 2 4 4 3,也可能是别的样子。 小可可希望知道,根据他们看清楚的这部分数字,能不能推断出这些数字里最少能有多少个逆序对。

    Input

    第一行两个正整数N和K。第二行N个整数,每个都是-1或是一个在1~K之间的数。

    Output

    一个正整数,即这些数字里最少的逆序对个数。

    Sample Input

    5 4
    4 2 -1 -1 3

    Sample Output

    4

    HINT

    4 2 4 4 3中有4个逆序对。当然,也存在其它方案得到4个逆序对。

    数据范围:
    100%的数据中,N<=10000,K<=100。
    60%的数据中,N<=100。
    40%的数据中,-1出现不超过两次。

    Source

    Day1

    题外话:

      刚开始看错题了,看成100%数据-1不超过2个,于是想这不是sb暴力吗?于是就开始敲代码,敲完之后就悲剧了。。。

      结果发现不会做。。。

      一看题解忽然明白了,我靠怎么还有这样一个性质,那就是 DP了。。。自己想的时候没想到DP QAQ。。。

     }

    题解:考虑一般情况 -1有很多,爆搜就不行了,那么应该如何下手呢?

             联想学过的知识,大概只有DP可以用了 

             但怎么DP呢?

             这些填的数应该有什么性质---一列数能有什么性质?大概就是递增递减吧。。。

             (吐槽:这思路也太牵强了吧。。。回答:。。。。。。)

            下面我们考虑两个空 a,b ,分别填上了x,y (假设只有两个空,并且x>y)

             如果我们交换 x 和 y 那么会有这样几条性质:

             1.[1,a-1],[b+1,n]中的数与x,y构成的逆序对没有发生改变

             2.[a+1,b-1]中 >max(x,y)的数与x,y构成的逆序对没有发生改变

             3.[a+1,b-1]中 < min(x,y)的数与x,y构成的逆序对没有发生改变

             4.[a+1,b-1]中处于区间(x,y)的数不再与x,y构成逆序对

             5.x,y不再构成逆序对

             也就是说我们交换x,y得到的答案一定会减小!

             稍微推广一下就是 这些填的数单调递增,但不一定是严格的

             考虑实现

             for i=1 to n do

              for j=1 to k do

                for p=1 to j do

                 f[i,j]=min(f[i,j],f[i-1,p]+cost(i,j))

             NO NO NO

             既然考虑到cost(i,j)是固定的,我们只需要求f[i-1,1],f[i-1,2]......f[i-1,j]的最小值即可

             前缀最小值优化!类似于前缀和。。。

             这样状态数一共有O(N*K)个,每个状态的转移的复杂度为O(1)

    代码:

     1 var f,g,big,sma:array[0..150000,0..150] of longint;
     2     ans,i,j,n,tot,k:longint;
     3     a,b:array[0..150000] of longint;
     4     function min(x,y:longint):longint;
     5      begin
     6       if x<y then exit(x) else exit(y);
     7      end;
     8 procedure init;
     9  begin
    10   readln(n,k);tot:=0;
    11   for i:=1 to n do
    12    begin
    13     read(a[i]);
    14     if a[i]=-1 then begin inc(tot);b[tot]:=i;end;
    15    end;
    16  end;
    17 procedure main;
    18  begin
    19   fillchar(big,sizeof(big),0);
    20   for i:=1 to n do
    21    for j:=1 to k do big[i,j]:=big[i-1,j]+ord(a[i]>j);
    22   fillchar(sma,sizeof(sma),0);
    23   for i:=n downto 1 do
    24    for j:=1 to k do sma[i,j]:=sma[i+1,j]+ord((a[i]<j) and (a[i]<>-1));
    25   fillchar(f,sizeof(f),0);
    26   for i:=1 to tot do
    27    begin
    28     f[i,1]:=f[i-1,1]+big[b[i],1]+sma[b[i],1];
    29     g[i,1]:=f[i,1];
    30     for j:=2 to k do
    31       begin
    32        f[i,j]:=g[i-1,j]+big[b[i],j]+sma[b[i],j];
    33        g[i,j]:=min(g[i,j-1],f[i,j]);
    34       end;
    35    end;
    36   ans:=maxlongint;
    37   for i:=1 to k do ans:=min(ans,f[tot,i]);
    38   for i:=1 to n do inc(ans,big[i,a[i]]);
    39   writeln(ans);
    40  end;
    41 begin
    42   assign(input,'input.txt');assign(output,'output.txt');
    43   reset(input);rewrite(output);
    44   init;
    45   main;
    46   close(input);close(output);
    47 end.
    48                        
    View Code

       

  • 相关阅读:
    【数据结构】算法 Tree Sub Structure 树的子结构
    【数据结构】算法 Binary Search Tree find Kth largest Node 二叉搜索树的第k大节点
    【数据结构】算法 Count Complete Tree Nodes 完全二叉树的节点个数
    【数据结构】算法 合并K个有序链表Merge k Sorted Lists
    JVisualVM 插件安装中出现网络问题
    [ISSUE] Logback TimeBasedRollingPolicy not rolling every day.
    【数据结构】算法 计算数组中的逆序对
    JQ为元素添加class
    时间戳转换成日期
    JS拖拽
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3897944.html
Copyright © 2011-2022 走看看