各种子序列问题

最长严格上升子序列

LIS问题,动归时间复杂度o(n2),可以用单调队列优化到o(nlogn)

http://blog.csdn.net/dangwenliang/article/details/5728363

#include
#include
#include
using namespace std;
int n,dp[5005],orz[5005],ans = 0;
int main(){
    cin>>n;
    for(int i = 1;i <= n;i++) scanf("%d",&orz[i]);
    for(int i = 1;i <= n;i++){
        dp[i] = 1;
        for(int j = 1;j < i;j++){
            if(orz[i] > orz[j])dp[i] = max(dp[i],dp[j]+1);
            ans = max(ans,dp[i]);
        }
    }
    cout<<ans;
    return 0;
}
#include 
using namespace std;
int find(int *a,int len,int n)//修改后的二分查找,若返回值为x,则a[x]>=n
{
    int left=0,right=len,mid=(left+right)/2;
    while(left<=right)
    {
       if(n>a[mid]) left=mid+1;
       else if(n1;
       else return mid;
       mid=(left+right)/2;
    }
    return left;
}
     
int main(void)
{
    int n,a[100],c[100],i,j,len;//新开一变量len,用来储存每次循环结束后c中已经求出值的元素的最大下标
    while(cin>>n)
    {
        for(i=0;i)
            cin>>a[i];
        b[0]=1;
        c[0]=-1;
        c[1]=a[0];
        len=1;//此时只有c[1]求出来,最长递增子序列的长度为1.
        for(i=1;i)
        {
            j=find(c,len,a[i]);
            c[j]=a[i];
            if(j>len)//要更新len,另外补充一点:由二分查找可知j只可能比len大1
                len=j;//更新len
        }
        cout<endl;
    }
    return 0;
}

合唱队形

#include
#include
#include<string>
#include
#include

using namespace std;
const int maxn = 200;
int dp[maxn],dps[maxn],value[maxn],n;

int main(){
    cin>>n;
    for(int i =1;i <= n;i++) cin>>value[i];
    dp[1] = dps[n] = 1;
    for(int i = 2;i <= n;i++){
        for(int j = 1;j < i;j++){
            if(dp[j] > dp[i] && value[i] > value[j]) dp[i] = dp[j];
        }
        dp[i]++;
        
    }
    for(int i = n-1;i >= 1;i--){
        for(int j = n;j > i;j--){
            if(dps[j] > dps[i] && value[i] > value[j]) dps[i] = dps[j];
        }
        dps[i]++;
        
    }
    int ans = 0;
    for(int i = 1;i <= n;i++) ans = max(ans,dp[i] + dps[i] - 1);
    cout< ans;
    return 0;
}

 

转载于:https://www.cnblogs.com/hyfer/p/5811926.html

你可能感兴趣的:(各种子序列问题)