洛谷 P1704 寻找最优美做题曲线

传送门:洛谷 P1704 寻找最优美做题曲线
算法分析:
这道题运用的是最长上升子序列,先对 \(p\) 数组进行排序,然后在数组中查询一遍,剔除不满足 \(c[p[i]]<c[j]<c[p[i+1]]\) 的数,最后做一遍 \(LIS\) 即可

时间复杂度:\(O(2nlog_n+n^2)\)


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxK=250000,maxN=500000;
int n,k,p[maxK+1],c[maxN+1],ans=0;
int dp[maxN+1],a[maxN+1],l=0;
int LIS();
inline int read();
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=k;i++) p[i]=read();
    sort(p+1,p+k+1);
    for(int i=1;i<=n;i++) c[i]=read();
    for(int i=2;i<=k;i++)
        if(c[p[i-1]]>=c[p[i]])
        {
            printf("impossible");
            return 0;
        }
    for(int i=1;i<p[1];i++)
        if(c[i]<c[p[1]]) a[l++]=c[i];
    a[l++]=c[p[1]];
    for(int i=1;i<k;i++)
    {
        for(int j=p[i];j<p[i+1];j++)
            if(c[p[i]]<c[j] && c[j]<c[p[i+1]])
                a[l++]=c[j];
        a[l++]=c[p[i+1]];
    }
    for(int i=p[k];i<=n;i++)
        if(c[i]>c[p[k]]) a[l++]=c[i];
    printf("%d",LIS());
    return 0;
}
int LIS()
{
    int len=1; dp[0]=a[0];
    for(int i=1;i<l;i++)
    {
        int j=lower_bound(dp,dp+len,a[i])-dp;
        if(j<len) dp[j]=a[i];
        else dp[len++]=a[i];
    }
    return len;
}
inline int read()
{
    int num=0,f=1;
    char ch=getchar();
    while((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if(ch=='-') {f=-1; ch=getchar();}
    while(ch>='0' && ch<='9')
    {
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

猜你喜欢

转载自www.cnblogs.com/ezsyshx/p/10359350.html