1049: [HAOI2006]数字序列 - BZOJ

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第三(前两名是怎么回事......)

posted @ 2014-04-08 11:19  Randolph87  阅读(347)  评论(0编辑  收藏  举报