【BZOJ】【1049】【HAOI2006】数字序列

DP


  第一问比较水……a[i]-=i 以后就变成最长不下降子序列问题了,第二问这个结论好神奇,考试的时候怎么破?大胆猜想,不用证明?TAT

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

 

没有将a[0]置为-INF在BZOJ上WA了……so sad……

 1 /**************************************************************
 2     Problem: 1049
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:260 ms
 7     Memory:2912 kb
 8 ****************************************************************/
 9  
10 //BZOJ 1049
11 #include<vector>
12 #include<cstdio>
13 #include<cstring>
14 #include<cstdlib>
15 #include<iostream>
16 #include<algorithm>
17 #define rep(i,n) for(int i=0;i<n;++i)
18 #define F(i,j,n) for(int i=j;i<=n;++i)
19 #define D(i,j,n) for(int i=j;i>=n;--i)
20 #define pb push_back
21 using namespace std;
22 inline int getint(){
23     int v=0,sign=1; char ch=getchar();
24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
26     return v*sign;
27 }
28 const int N=35010,INF=~0u>>2;
29 typedef long long LL;
30 /******************tamplate*********************/
31 int head[N],to[N],next[N],cnt;
32 void ins(int x,int y){
33     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
34 }
35 int n,a[N],b[N],f[N],len;
36 int Find(int x){
37     int l=1,r=len,mid,ans=0;
38     while(l<=r){
39         mid=l+r>>1;
40         if (b[mid]<=x) ans=mid,l=mid+1;
41         else r=mid-1;
42     }
43     return ans+1;
44 }
45 LL g[N],sum1[N],sum2[N];
46 void solve2(){
47     D(i,n,0){
48         ins(f[i],i);
49         g[i]=1LL<<60;
50     }
51     g[0]=0; 
52     a[0]=-1<<30;//这句必须有,不然在BZOJ上会WA……
53     F(x,1,n)
54         for(int i=head[f[x]-1];i;i=next[i]){//枚举从哪个地方转移过来
55             if (to[i]>x) break;
56             if (a[to[i]]>a[x]) continue;
57             for(int k=to[i];k<=x;k++)
58                 sum1[k]=abs(a[k]-a[to[i]]),sum2[k]=abs(a[x]-a[k]);
59             for(int k=to[i]+1;k<=x;k++)
60                 sum1[k]+=sum1[k-1],sum2[k]+=sum2[k-1];
61             for(int k=to[i];k<x;k++)
62                 g[x]=min(g[x],g[to[i]]+sum1[k]-sum1[to[i]]+sum2[x]-sum2[k]);
63         }
64     cout <<g[n]<<endl;
65 }
66 int main(){
67     n=getint();
68     F(i,1,n) a[i]=getint()-i;
69     a[++n]=1<<30;
70     F(i,1,n){
71         int x=Find(a[i]);
72         f[i]=x; b[x]=a[i];
73         if (x>len) len=x;
74     }
75 //  F(i,1,n) printf("%d ",f[i]);puts("");
76     printf("%d\n",n-f[n]);//task 1 end
77     solve2();
78     return 0;
79 }
View Code

1049: [HAOI2006]数字序列

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1022  Solved: 410
[Submit][Status][Discuss]

Description

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

Input

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

Output

第一行一个整数表示最少需要改变多少个数。 第二行一个整数,表示在改变的数最少的情况下,每个数改变的绝对值之和的最小值。

Sample Input

4
5 2 3 5

Sample Output

1
4

HINT

【数据范围】

90%的数据n<=6000。

100%的数据n<=35000。

保证所有数列是随机的。

Source

[Submit][Status][Discuss]
posted @ 2015-04-16 18:10  Tunix  阅读(320)  评论(0编辑  收藏  举报