第一次在CSDN上寫博客,紀念一下。
題意:1<=N<=1000大小的1<=ai<=1000的數組,最多有多少對滿足a(i+1)>ai;即嚴格上升的順序
鏈接:http://codeforces.com/contest/651/problem/B
這道題 virtual 的時候過了,不過做這道題用的時間用了比較久,手速慢。賽完後看了一下帆神的代碼,竟然辣麼短,而且不理解什麼意思,百度了一下其他題解才弄明白
我的方法:每次循環都產生出一個嚴格上升的序列,把序列的長度加到答案上,然後把此序列中的數在原序列中刪除,重複操作遍歷原數列所有數後的ans即最優解,最壞的時間複雜度O(n^2*logn)(循環n次,每次快排n*logn)
更好的方法:上述方法中每次找到第K個嚴格上升的序列加到遍歷過的K-1序列之後的ans就是(n-1)-K,因爲每次生成一個序列就和前面的序列斷開了一個,一共有n-1個間隔,所以最優解即找到max(數組中出現次數最多的數出現的次數),然後(n-1)-max即可,複雜度爲O(n*logn)(快排之後做)或者O(n)(開數組num[a]記錄數字a出現的次數,當a的範圍過大時會超內存而不適用,此題a<=1000,可以用)
我的代碼:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
using namespace std;
int n;
int cnt;
int ma[1010];
int ans;
int cmp(const void*a,const void*b){
return *(int*)b-*(int*)a;
}
int main()
{
int i,j;
int tmp;
int flag;
while(~scanf("%d",&n)){
memset(ma,0,sizeof(ma));
for(i=1;i<=n;i++){
scanf("%d",&ma[i]);
}
ans=0;cnt=n;
while(cnt>0){
qsort(ma+1,n,sizeof(ma[0]),cmp);
tmp=0;
flag=-1;
for(i=1;i<cnt;i++){
if(ma[i]!=ma[i+1]){
tmp++;
ma[i]=0;
flag=i+1;
}
else
;
}
if(flag!=-1)
ma[flag]=0;
ans+=tmp;
cnt-=tmp+1;
}
printf("%d\n",ans);
}
return 0;
}
O(n*logn)代碼
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define N 100010
using namespace std;
int a[N];
int n;
int main()
{
int i;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
int ans=0,tmp=0;
for(i=1;i<=n;i++)
{
while(i<=n&&a[i]==a[i-1])
{ans++;i++;}
tmp=max(tmp,ans);
ans=0;
}
ans=n-1-tmp;
printf("%d\n",ans);
return 0;
}
O(n)代碼
#include <cmath>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 1005
inline int mini(int a, int b)
{
return a < b ? a : b;
}
inline int maxi(int a, int b)
{
return a > b ? a : b;
}
int num[maxn];
int main()
{
int n, t, m = -1, ans = 0;
scanf("%d", &n);
for (int i = 0; i < n; ++i)
{
scanf("%d", &t);
num[t]++;
}
for (int i = 1; i < maxn; ++i)
m = maxi(m, num[i]);
ans = n - m;
printf("%d\n", ans);
return 0;
}