HDU 5256 - 序列变换 ,树状数组+离散化 ,二分法
Problem Description
我们有一个数列A1,A2...An,你现在要求修改数量最少的元素,使得这个数列严格递增。其中无论是修改前还是修改后,每个元素都必须是整数。
请输出最少需要修改多少个元素。
请输出最少需要修改多少个元素。
Input
第一行输入一个T(1≤T≤10),表示有多少组数据
每一组数据:
第一行输入一个N(1≤N≤105),表示数列的长度
第二行输入N个数A1,A2,...,An。
每一个数列中的元素都是正整数而且不超过106。
每一组数据:
第一行输入一个N(1≤N≤105),表示数列的长度
第二行输入N个数A1,A2,...,An。
每一个数列中的元素都是正整数而且不超过106。
Output
对于每组数据,先输出一行
Case #i:
然后输出最少需要修改多少个元素。
Case #i:
然后输出最少需要修改多少个元素。
Sample Input
2
2
1 10
3
2 5 4
Sample Output
Case #1: 0 Case #2: 1
解题思路:
不难理解,求 a[i]-i 的最长非递减子序列长度 len ,然后 n-len 就是答案了;
以下有两份代码;
代码一:
二分法,打模板即可;时间复杂度O(nlog(n))
代码二:
树状数组,前缀最大值的应用。 时间复杂度也是 O(nlog(n))
回想求LIS的动态规划过程 dp[i]=max(dp[j]); (i>j&&h[j]<h[i])
利用树状数组的性质: dp[i]=query(a[i]);
但这道题上还有很多问题,比如负数的存在,应此需要离散化;
应注意离散化后再去标记最大值,WA了好久好久..
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 int c[1000000],n,t,len,a; 5 int find(int l,int r,int num){ 6 while(l<=r){ int mid=(l+r)>>1; if(c[mid]<=num) l=mid+1; else r=mid-1; } 7 return l; 8 } 9 int main(){ 10 scanf("%d",&t); 11 for(int k=1;k<=t;k++){ 12 printf("Case #%d:\n",k); 13 scanf("%d",&n); 14 len=1; memset(c,0,sizeof(c)); 15 for(int i=1;i<=n;i++){ 16 scanf("%d",&a); 17 if(i==1){ c[len]=a-i; continue; } 18 int pos=find(1,len,a-i); 19 c[pos]=a-i; 20 if(len<pos) len=pos; 21 } printf("%d\n",n-len); 22 } return 0; 23 }
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 using namespace std; 5 #define N 1000000+5 6 int c[N],a[N],b[N],n,t,nmax; 7 void modify(int x,int num){while(x<=nmax)c[x]=max(c[x],num),x+=x&-x;} 8 int query(int x){int s=0;while(x>0)s=max(c[x],s),x-=x&-x;return s;} 9 int main(){ 10 scanf("%d",&t); 11 for(int k=1;k<=t;k++){ 12 printf("Case #%d:\n",k); 13 scanf("%d",&n); 14 memset(c,0,sizeof(c)); nmax=0; 15 for(int i=0;i<n;i++){ 16 scanf("%d",&a[i]); 17 a[i]-=i; b[i]=a[i]; 18 } 19 sort(b,b+n); 20 int size=unique(b,b+n)-b;//离散化 21 for(int i=0;i<n;i++){ 22 a[i]=lower_bound(b,b+size,a[i])-b+1; 23 nmax=max(a[i],nmax);//离散化以后再去标记最大值 24 } 25 for(int i=0;i<n;i++)modify(a[i],query(a[i])+1);//前缀最大值+1 26 printf("%d\n",n-query(nmax)); 27 } return 0; 28 }
我自倾杯,君且随意