题解/算法 {F - Useless for LIS}

题解/算法 {F - Useless for LIS}

@LINK: https://atcoder.jp/contests/abc354/tasks/abc354_f;

求哪些元素可以出现在LIS里

二分求LIS里的DP定义是: DP[I]表示 长度为I的LIS 其末尾元素的最小值; 在求LIS的过程中 对于每个元素A[i], 我们是求出了一个len 他表示 A[0...i]里 以A[i]为结尾的LIS的最长长度 (于是DP记录DP[len] = i);

我们在DP过程中, 再反向记录一下 即Rec[i] = len, 表示 以A[i]为结尾的LIS 最长长度为len;

最终, 我们逆序遍历整个数组, 维护一个Height[ len]表示 长度为len的LIS 其末尾元素的最大值;
对于当前A[i], 如果Height[ Rec[i] + 1] > A[i] 则当前可以是答案;
比如[1, 8,9, 2, 3, 4], 当到达9时 此时Height[4]=4, Height[3]=3, [2]=2, 因为Rec[9] = 3Height[4]=4 < 9 所以 9不是答案 他也不能更新Height;

代码

int N; cin>> N;
vector<int> A(N); for( auto & i : A){ cin>> i;}
vector<int> Rec(N);
//{ ___LIS
auto ___LIS = [&]( int const* _arr, int _length){
    for( int i = 0; i < _length; ++i){
        ...
        Rec[i] = len; // 记录
    }
    return MaxLen;
};
//} ___LIS
auto maLen = ___LIS( A.data(), A.size());

vector<char> ANS( N, 1);
vector<int> Height( N+10, -2e9); // `Height[x]=y` 长度为x的LIS 其末尾元素的最大值;
FORrev_( i, N-1, 0){
    if( Rec[i]!=maLen && Height[ Rec[i]+1] <= A[i]){
        ANS[i] = 0;
        continue; // 注意这里;
    }
    Height[ Rec[i]] = A[i]; // 这里不用取`max`, 因为他一定是单调的(即每次更新的值 不会比当前小);
}

FOR_( i, 0, N-1){
    if( ANS[i]){ cout<< i<< " ";}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值