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