hdu5489Removed Interval 最长递增子序列

来源:互联网 发布:数控转塔冲床编程视频 编辑:程序博客网 时间:2024/05/16 02:02
//给一个长度为n的序列//在其中去除长度为l的连续的序列//剩下的序列的最长递增子序列的最长的长度为多少//维护两个数组,前面一个数组//数组a[i] 表示从前到后,长度为i的最后一个数的最小值//数组b[i] 表示从后往前,长度为i的最大得一个数//然后从前到后遍历,//由于每前进一位,a[i] , 和b[i]只改变一个数//所以只需要对于那个更新的数在另一边用二分找一下就行#include<cstdio>#include<cstring>#include<iostream>#include<map>using namespace std ;const int maxn = 1e5+10 ;int a[maxn] , b[maxn] ;int c[maxn] ;pair<int , int> pre[maxn] ;int len_b = 0 ;int len_a = 0 ;int find_b(int l , int r , int v) //找第一个小于它的数{    while(l<=r)                   //在一个递减序列中    {        int mid = (l+r)>> 1 ;        if(b[mid] > v)        l = mid+1 ;        else r = mid - 1 ;    }    return l;}int find_a(int l , int r ,int v) //找第一个大于它的数{                                 //在一个递增序列中    while(l<=r)    {        int mid = (l + r) >> 1 ;        if(a[mid] < v)        l = mid+1 ;        else r = mid - 1 ;    }    return l ;}int find_ans_a(int l , int r , int v) //在一个递增序列找第一个小于它的数{    while(l<=r)    {        int mid = (l+r)>>1 ;        if(a[mid] < v)        l = mid + 1 ;        else r = mid - 1 ;    }    return r ;}int find_ans_b(int l , int r , int v)//在一个递减序列中找第一个大于它的数{    while(l<=r)    {        int mid = (l+r) >> 1 ;        if(b[mid] > v)        l = mid + 1 ;        else r = mid - 1 ;    }    return r ;}int main(){    //freopen("in.txt" , "r" , stdin) ;    int t ;    scanf("%d" , &t) ;    int cas = 0 ;    while(t--)    {        int n , l ;        scanf("%d%d" , &n , &l) ;        for(int i = 1;i <= n;i++)        a[i] = b[i] = 0 ;        for(int i = 1;i <= n;i++)        scanf("%d" , &c[i]) ;        len_a = len_b  = 0 ;        for(int j = n;j > l;j--)        {            int pos = find_b(1 , len_b , c[j]) ;            pre[j] = make_pair(pos , b[pos]) ;            if(!b[pos])len_b++ ;            b[pos] = c[j] ;        }        int ans = len_b ;        for(int i = 1;i <= n-l;i++)        {            int pos = find_a(1 , len_a , c[i]) ;            if(a[pos] == 0)len_a++ ;            a[pos] = c[i] ;            pair<int , int> tmp = pre[i+l] ;            if(tmp.second == 0)len_b--;            else b[tmp.first] = tmp.second ;            int pos_1 = find_ans_b(1  , len_b , c[i]) ;            ans = max(pos+pos_1 , ans) ;            if(tmp.second != 0)            {                int pos_2 = find_ans_a(1 , len_a , tmp.second) ;                ans = max(ans , pos_2 + tmp.first) ;            }        }        printf("Case #%d: " , ++cas) ;        printf("%d\n" , ans) ;    }    return  0 ;}
0 0
原创粉丝点击