The 16th Zhejiang Provincial Collegiate Programming Contest Sponsored E.Sequence in the Pocket(思维题)
题意:
给出一个序列,你可以将任意一个数移到最前面;
求最少需要移动多少次,可以是此序列变成非递减序列;
思路:
定义 (ai,aj) 为逆序对 ( i < j , ai > aj ), 求出 aj 的最大值,用变量 curMax 存储;
遍历一遍数组,求解 ans;
对于∀ i ∈[1,n]
①如果 ai < curMax , ans++;
②如果 ai == curMax , 那么需要特殊判断:
(2.1)如果 ai 之前不曾出现比 curMax 大的数,不需要移动;
(2.2)反之,ans++;
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+50; 4 5 int n; 6 int a[maxn]; 7 int preMax[maxn];///preMax[i]:[1,i]的最大值 8 9 int Solve() 10 { 11 int curMax=0; 12 for(int i=n;i >= 1;--i) 13 if(a[i] < preMax[i-1])///找逆序对(x,y)的最大的y 14 curMax=max(curMax,a[i]); 15 int ans=0; 16 bool flag=false; 17 for(int i=1;i <= n;++i) 18 { 19 if(a[i] > curMax)///判断[1,i]有无比curMax大的数出现 20 flag=true; 21 if(a[i] < curMax)///情况① 22 ans++; 23 if(flag && a[i] == curMax)///情况2.2 24 ans++; 25 } 26 return ans; 27 } 28 int main() 29 { 30 int test; 31 while(~scanf("%d",&test)) 32 { 33 while(test--) 34 { 35 scanf("%d",&n); 36 preMax[0]=0; 37 for(int i=1;i <= n;++i) 38 { 39 scanf("%d",a+i); 40 preMax[i]=max(preMax[i-1],a[i]); 41 } 42 printf("%d\n",Solve()); 43 } 44 } 45 return 0; 46 }
求逆序对(x,y)中最大的y 需要树状数组求么????
答案是否定的,直接遍历一遍,记录一下前i个数得最大值就好了;
but,比赛的时候,用的是树状数组求最大的y;
按理说,树状数组求逆序对是树状数组最基本的操作(quq,逃);
代码写搓可还行(debug俩小时,然鹅,还没该对,以至于我都开始怀疑数据了);
经过这次debug,这辈子都不会写搓树状数组求逆序对得代码了;
学弟思路(tql):
遍历一遍数组 a ,判断最多有多少个连续得最大值,假设有 x 个,输出 n-x;
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+50; 4 5 int n; 6 int a[maxn]; 7 int b[maxn]; 8 9 int Solve() 10 { 11 memcpy(b+1,a+1,sizeof(int)*n); 12 sort(b+1,b+n+1); 13 int ans=n; 14 for(int i=n;i >= 1;--i) 15 if(b[ans] == a[i])///判断最多的连续的最大值 16 ans--; 17 return ans; 18 } 19 int main() 20 { 21 int test; 22 while(~scanf("%d",&test)) 23 { 24 while(test--) 25 { 26 scanf("%d",&n); 27 for(int i=1;i <= n;++i) 28 scanf("%d",a+i); 29 printf("%d\n",Solve()); 30 } 31 } 32 return 0; 33 }