首页 > 代码库 > 【动态规划】【最长上升子序列】【贪心】bzoj1046 [HAOI2007]上升序列

【动态规划】【最长上升子序列】【贪心】bzoj1046 [HAOI2007]上升序列

nlogn求出最长上升子序列长度。

对每次询问,贪心地回答。设输入为x。当前数a[i]可能成为答案序列中的第k个,则若 f[i]>=x-k && a[i]>ans[k-1] 即可。

f[i]表示以a[i]开头的最长上升子序列长度。

但这个东西难以统计。so 我们将原序列反序,求f[i] 表示以 a[i]为结尾的最长下降子序列长度即可。最后再将f、a reverse一下。

 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 int a[10001],n,m,en=1,len,last; 5 int b[10001];//b[i]:将a翻转后,长度为i的最长下降子序列的末尾 6 int c[10001];//c[i]:将a翻转后,以a[i]开头的最长下降子序列的长度 7 bool cmp(const int &a,const int &b){return a>b;} 8 int main() 9 {10     scanf("%d",&n);11     for(int i=1;i<=n;i++) scanf("%d",&a[n-i+1]);12     scanf("%d",&m);13     b[1]=a[1]; c[1]=1;14     for(int i=2;i<=n;i++)15       {16           int *p=lower_bound(b+1,b+en+1,a[i],cmp);17           if(!(*p)) ++en;18           *p=a[i];19           c[i]=p-b;20       }21     for(int i=1;i<=(n>>1);i++) swap(c[i],c[n-i+1]),swap(a[i],a[n-i+1]);22     for(int i=1;i<=m;i++)23       {24           scanf("%d",&len);25           if(len>en)26             {27                 puts("Impossible");28                 continue;29             } last=0;30           for(int j=1;j<=n;++j)31             if(c[j]>=len&&a[j]>last)32               {33                 printf("%d",last=a[j]);34                 if(!(--len))35                   {36                     puts("");37                     break;38                   } putchar( );39               }40       }41     return 0;42 }

【动态规划】【最长上升子序列】【贪心】bzoj1046 [HAOI2007]上升序列