做了一上午血亏
还好最后搞明白一点点;
这是一道dp(最长上升子序列)和贪心题
dp倒是简单 主要是贪心的证明 很难理解 不多做记录了,看了一些题解,感觉讲的都一般,yxc的视频讲解还不错 , 但是他做的是小数据范围, 可以用二分优化一波;
该文件无法打开 - AcWing yxc视频讲解
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std ;
const int N = 1e5 +100 ;
int a[N] , b[N] ;
int n ;
int q[N] ;
int main(){
while(cin >> a[n]) n ++ ;
int ans = 0 ;
for(int i = n - 1 ; i >= 0 ; i --){
b[i] = a[n-i-1] ;
}
//第一问就是最长上升子序列问题
for(int i = 0 ; i < n ; i ++){
int l = 0 , r = ans ;
while(l < r) {
int mid =(r+l+1) >> 1 ;
if(q[mid] <= b[i]) l = mid ;
else r = mid - 1 ;
}
ans = max(r+1,ans) ;
q[r+1] = b[i] ;
}
cout << ans << endl;
memset(q,0,sizeof(q)) ;
//第二题主要考察了贪心思想,尤为难做
//我们遍历每一个数值,找到当前放到结尾大于等于它的最小的序列的后面
//先遍历每个数,再从已经有的序列中找符合上面条件的
//找到以后进行处理:如果当前没有比a[i]更大的数 那他只能自己新开一个序列
然后更新长度也就是子序列的个数(有几个子序列)
然后将我们处理的这个子序列的最后一个结尾数更新成a[i]
int len = 0 ;
for(int i = 0 ; i < n ;i ++){
int l = 0 ,r = len ;
while(l < r){
int mid = (l + r + 1) >> 1 ;
if(q[mid] <= a[i]) l = mid ;
else r = mid - 1 ;
}
if(q[r]< a[i]) r ++ ;
len = max(len , r) ;
q[r] = a[i] ;
}
cout << len << endl ;
}