现在我们有一个长度为n的整数序列A。但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列。但是不希望改变过多的数,也不希望改变的幅度太大。
标签:
第一问比较水……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 }
现在我们有一个长度为n的整数序列A。但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列。但是不希望改变过多的数,也不希望改变的幅度太大。
第一行包含一个数n,接下来n个整数按顺序描述每一项的键值。
第一行一个整数表示最少需要改变多少个数。 第二行一个整数,表示在改变的数最少的情况下,每个数改变的绝对值之和的最小值。
【数据范围】
90%的数据n<=6000。
100%的数据n<=35000。
保证所有数列是随机的。
标签:
原文地址:http://www.cnblogs.com/Tunix/p/4432882.html