1. 程式人生 > >【bzoj5427】最長上升子序列

【bzoj5427】最長上升子序列

題目連結

額。。我簡直像個智障啊。。想了一個錯的解還給學弟們比比半天。。然後學弟們也沒指出錯誤。。

首先考慮最優方案肯定是把所有的 N 都裝進去

為什麼呢?

(因為沒有找到證明,智障我就自己想了一個)
我們考慮有兩個下標 i

j ,其中 i < j
s
u m i
i 之前的 N 的數量
如果中間的
N
的個數過少,能裝進 a i a j 之間的空隙中,即 s u m j s u m i a i a j ,那把 N 給填完顯然優
如果中間的 N 的個數太多,裝不進 a i a j 之間的空隙中,即 s u m j s u m i > a i a j
那麼我們顯然可以找到以 i 結尾的 L I S 的上一個數,這一個數肯定比 a i 小,於是我們便可以再塞幾個 N 進去,而從 i 往回找上一個數只會使得 L I S 的長度減小 1 ,再塞幾個 N 進去會使得 L I S 長度增加至少 1 ,那我只要一直做這個過程直到 N 填完了就好了

所以把所有 N 都給塞進去是最優的

那這樣就好做了,我們重新定義一個數組 b i = a i s u m i ,對 b 陣列跑LIS就行了

雙倍經驗 bzoj 4282

程式碼

#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<cstring>
#include<cmath>
using namespace std;

typedef long long LL;
typedef double DL;

const int INF = 1000000000;
const int maxn = 200010;

struct que{
    char c; int x;
}opt[maxn];

int n,m,ans,cnt;
int maxx[maxn],f[maxn];
int ha[maxn],data[maxn],tot,N;

inline LL getint()
{
    LL ret = 0,f = 1;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') 
        ret = ret * 10 + c - '0',c = getchar();
    return ret * f;
}

inline char getcom()
{
    char c = getchar();
    while (c != 'K' && c != 'N') 
        c = getchar();
    return c;
}

int main()
{
    #ifdef AMC
        freopen("AMC1.txt","r",stdin);
    #endif
    n = getint();
    for (int i = 1; i <= n; i++)
    {
        opt[i].c = getcom();
        cnt += opt[i].c == 'N';
        if (opt[i].c == 'K')
            data[++tot] = opt[i].x = getint() - cnt;
    }

    sort(data + 1,data + tot + 1);
    for (int i = 1; i <= tot; i++)
        if (i == 1 || data[i] != data[i - 1])
            ha[++N] = data[i];

    for (int i = 1; i <= n; i++)
    {
        if (opt[i].c == 'N') continue;
        opt[i].x = lower_bound(ha + 1,ha + N + 1,opt[i].x) - ha;
        for (int j = opt[i].x - 1; j; j -= j & -j)
            f[i] = max(f[i],maxx[j]);
        f[i]++;
        for (int j = opt[i].x; j <= N; j += j & -j)
            maxx[j] = max(maxx[j],f[i]);
        ans = max(ans,f[i]);
    }
    printf("%d\n",ans + cnt);
    return 0;
}