2016/11/12

我终于打拍了,分数果然好看了很多。

但是并没有A掉第三题

做法:求最长上升子序列

有两个原因:
1.想多了,,以为要从上升和下降中取最优值,,结果还丢分了

2.虽然看过nlogn的最长上升子序列求法 ,但是并没有仔细看,考试的时候自己瞎扯了一个90分算法(实在想不起log是哪里来的了)

看了nlogn的做法后,发现差别在于我没有使用二分查找,改进之后会快很多

首先附上90分的瞎扯代码

 1 #include<iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdio>
 5 using namespace std;
 6 int n,a[200010],f[200010],d[200010];
 7 void inti()
 8 {
 9     scanf("%d",&n);
10     for(int i=1;i<=n;i++)
11     {
12          scanf("%d",&a[i]);
13          f[i]=200005;
14     }
15 }
16 void work()
17 {
18     int j,sum1=0,sum2=0,ans,s;
19     d[0]=200005;
20     for(int i=1;i<=n;i++)
21     {
22        s=0;
23        for(j=0;j<=sum1;j++)//up
24        {
25            
26         //    cout<<a[i]<<" "<<f[j]<<" "<<f[j+1]<<endl;  
27             if(a[i]>=f[j]&&a[i]<f[j+1])
28             {
29                 f[j+1]=a[i];
30                 s=j+1;
31                 break;
32             } 
33        }
34         sum1=max(s,sum1);  
35        s=0;
36        for(j=0;j<=sum2;j++)//down 其实并不用求下降的部分
37        {
38              if(a[i]<=d[j]&&a[i]>d[j+1])
39             {
40                 d[j+1]=a[i];
41                 s=j+1;
42                 break;
43             } 
44            
45        }
46         sum2=max(s,sum2);
47     }   
48    // cout<<sum1<<" "<<sum2<<endl;
49     ans=n-(max(sum1,sum2));
50     printf("%d",ans);
51 }
52 int main()
53 {
54     freopen("cmi.in","r",stdin);
55     freopen("cmi.out","w",stdout);
56      inti();
57      work();
58      return 0;
59 }
View Code

然后正确的使用姿势是要二分当前数字可以插入的地方

 1 #include<iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdio>
 5 using namespace std;
 6 int n,a[200010],f[200010],len;
 7 inline int read()
 8 {
 9     char ch=getchar();
10     int f=1,x=0;
11     while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}
13     return x*f;
14 } 
15      
16 void inti()
17 {
18     n=read();
19     for(int i=1;i<=n;i++)
20     {
21         a[i]=read();
22          f[i]=200005;
23     }
24 }
25 int find(int i)
26 {
27     int left,right,mid;
28     left=0,right=len;
29     while(left<right)
30    {
31           mid=left+(right-left)/2;
32           if(f[mid]>=a[i]) right=mid;
33           else left=mid+1;
34    }
35    return left;
36 }
37 void work()
38 {
39     int ans,pos;
40     for(int i=1;i<=n;i++)
41     {
42        if(a[i]>f[len]) f[++len]=a[i];
43        else 
44        {
45             pos=find(i);
46             f[pos]=a[i]; 
47        }
48      
49     }   
50     ans=n-len;
51     printf("%d",ans);
52 }
53 int main()
54 {
55     freopen("cmi.in","r",stdin);
56     freopen("cmi.out","w",stdout);
57      inti();
58      work();
59      return 0;
60 }
View Code

第二题先留坑,并没有看懂标程

以上By Native_carrot

原文地址:https://www.cnblogs.com/LQ-double/p/6056731.html