【bzoj5427】最長上升子序列
阿新 • • 發佈:2018-11-19
題目連結
額。。我簡直像個智障啊。。想了一個錯的解還給學弟們比比半天。。然後學弟們也沒指出錯誤。。
首先考慮最優方案肯定是把所有的 都裝進去
為什麼呢?
(因為沒有找到證明,智障我就自己想了一個)
我們考慮有兩個下標
,其中
記
為
之前的
的數量
如果中間的
的個數過少,能裝進
和
之間的空隙中,即
,那把
給填完顯然優
如果中間的
的個數太多,裝不進
和
之間的空隙中,即
那麼我們顯然可以找到以
結尾的
的上一個數,這一個數肯定比
小,於是我們便可以再塞幾個
進去,而從
往回找上一個數只會使得
的長度減小
,再塞幾個
進去會使得
長度增加至少
,那我只要一直做這個過程直到
填完了就好了
所以把所有 都給塞進去是最優的
那這樣就好做了,我們重新定義一個數組 ,對 陣列跑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;
}