传送门:洛谷 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;
}