zoukankan      html  css  js  c++  java
  • 1049: [HAOI2006]数字序列

    Description

    现在我们有一个长度为n的整数序列A。但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列。但是不希望改变过多的数,也不希望改变的幅度太大。
    Input

    第一行包含一个数n,接下来n个整数按顺序描述每一项的键值。
    Output

    第一行一个整数表示最少需要改变多少个数。 第二行一个整数,表示在改变的数最少的情况下,每个数改变的绝对值之和的最小值。
    Sample Input
    4
    5 2 3 5
    Sample Output
    1
    4

    【数据范围】
    90%的数据n<=6000。
    100%的数据n<=35000。
    保证所有数列是随机的。

    这个算法的复杂度真的是O(n^2)吗?怎么我觉得不对呢

    和机房的小伙伴讨论之后,觉得这个复杂度应该是O(n^3)的(虽然跑得很快)

    先转换一下,b[i]=a[i]-i,然后就是求b的最长不下降了,这样好算代价一些

    cost[i]=cost[j]+w(j,i)(f[j]=f[i]-1,j<i)

    计算w的时候有一个定理,肯定有一种最优方案是把左半边变成b[j]右半边变成b[i]

    证明:http://pan.baidu.com/share/link?uk=2651016602&shareid=1490516411

     1 const
     2     maxn=35010;
     3     inf=1000000000;
     4 var
     5     a,f,b,first,next,last:array[0..maxn]of longint;
     6     g:array[0..maxn]of int64;
     7     n,tot,max:longint;
     8  
     9 procedure insert(x,y:longint);
    10 begin
    11     inc(tot);
    12     last[tot]:=y;
    13     next[tot]:=first[x];
    14     first[x]:=tot;
    15 end;
    16  
    17 procedure find(x:longint);
    18 var
    19     l,r,mid:longint;
    20 begin
    21     l:=1;
    22     r:=n;
    23     while l<>r do
    24       begin
    25         mid:=(l+r)>>1;
    26         if b[mid]>a[x] then r:=mid
    27         else l:=mid+1;
    28       end;
    29     if max<l then max:=l;
    30     f[x]:=l;
    31     b[l]:=a[x];
    32     insert(l,x);
    33 end;
    34  
    35 procedure init;
    36 var
    37     i:longint;
    38 begin
    39     read(n);
    40     for i:=1 to n do
    41       begin
    42         read(a[i]);
    43         dec(a[i],i);
    44       end;
    45     inc(n);
    46     a[n]:=inf-1;
    47     a[0]:=-inf;
    48     for i:=1 to n do
    49       b[i]:=inf;
    50     insert(0,0);
    51 end;
    52  
    53 function calc(l,r:longint):int64;
    54 var
    55     i:longint;
    56     s:int64;
    57 begin
    58     s:=0;
    59     for i:=l to r do
    60       inc(s,abs(a[i]-a[r]));
    61     calc:=s;
    62     for i:=l to r do
    63       begin
    64         s:=s-abs(a[i]-a[r])+abs(a[i]-a[l]);
    65         if calc>s then calc:=s;
    66       end;
    67 end;
    68  
    69 procedure work;
    70 var
    71     i,j:longint;
    72     num:int64;
    73 begin
    74     for i:=1 to n do
    75       begin
    76         find(i);
    77         g[i]:=inf*inf;
    78         j:=first[f[i]-1];
    79         while j<>0 do
    80           begin
    81             if a[last[j]]<=a[i] then
    82               begin
    83                 num:=calc(last[j],i);
    84                 if g[i]>g[last[j]]+num then g[i]:=g[last[j]]+num;
    85               end;
    86             j:=next[j];
    87           end;
    88       end;
    89     writeln(n-max);
    90     write(g[n]);
    91 end;
    92  
    93 begin
    94     init;
    95     work;
    96 end.
    View Code

    pascal第三(前两名是怎么回事......)

  • 相关阅读:
    C#代码动态编译、动态执行、动态调试
    php’s explode() 函数
    exec函数族
    在C语言中执行shell命令
    dmesg简介
    错误输出
    php’s json_decode函数
    使expect脚本传回返回值
    php’s fgets() 函数
    统计当前目录下的所有文件目录大小,不显示子目录与子文件
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3651579.html
Copyright © 2011-2022 走看看