1. 程式人生 > >BZOJ - 5427:最長上升子序列 (二分&思維)

BZOJ - 5427:最長上升子序列 (二分&思維)

現在給你一個長度為n的整數序列,其中有一些數已經模糊不清了,現在請你任意確定這些整數的值, 使得最長上升子序列最長。(為何最長呢?因為hxy向來對自己的rp很有信心)   Input 第一行一個正整數n 接下來n行第i行格式如下      K x:表示第i個數可以辨認且這個數為x      N:表示第i個數一個已經辨認不清了 (n<=100000,|x|<=10^9)  

 

Output 一個正整數代表最長上升子序列最長是多少  

 

Sample Input 4 K 1 N K 2 K 3

Sample Output

題意:有一個序列,有些位置的數由你來決定,求LIS。

思路:首先我們知道求LIS可以用二分來優化,那麼我們維護一個上升的序列,用dp[i]表示長度為i的LIS的最後一位最小是多少,每次新加入一個數的時候,用x去替換upper_bound的位置即可。  

然而這個題有未知數,未知數可以由自己決定,所以每個未知數都要使用比較優,對於每個dp[i],可以用dp[i]+1去更新dp[i+1],即右移一位,我們用add來表示。

 

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=100010;
int dp[maxn],add;
int main()
{
    dp[0]=-(1e9+10);
    int N,x,R=0; char c[4];
    scanf("%d",&N);
    rep(i,1,N){
        scanf("%s",c+1);
        if(c[1]=='K'
){ scanf("%d",&x); int l=0,r=R,pos,mid; while(l<=r){ mid=(l+r)>>1; if(dp[mid]+add<x) { l=mid+1; pos=mid;} else r=mid-1; } if(pos==R) dp[++R]=x-add; else dp[pos+1
]=min(dp[pos+1],x-add); } else add++; } printf("%d\n",R+add); return 0; }