翻译:
Chanek先生给出了一个从1到𝑛的序列𝑎。将𝑓(𝑎)定义为𝑎𝑖=𝑖的索引数。
您可以从当前序列中选择一个元素并删除它,然后将其余元素连接在一起。例如,如果从序列[4,2,3,1]中删除第3个元素,则得到的序列将是[4,2,1]。
您希望使用零或多个操作从𝑎中删除一些元素,以最大化𝑓(𝑎)。找到最大的𝑓(𝑎)。
输入
第一行包含一个整数𝑛(1≤𝑛≤2⋅105)——序列的初始长度。
第二行包含𝑛整数𝑎1𝑎2,…,𝑎𝑛(1≤𝑎𝑖≤2⋅105)——初始序列𝑎。
输出
输出一个整数,表示可以通过执行零次或多次操作获得的最大𝑓(𝑎)。
例子
inputCopy
7
2 1 4 2 5 3 7
outputCopy
3.
inputCopy
4
4 2 3 1
outputCopy
2
请注意
在第一个例子中,执行如下操作,将𝑓(𝐴)=3。
(2、1、4、2、5、3、7]→[2,1、2、5、3、7]→[1、2、5、3、7]→[1、2、5、3]→[1,2,3]
在第二个例子中,𝑓(𝐴)=2,不需要其他操作。
思路:
对于𝑓(𝑎)定义为𝑎𝑖=𝑖的索引数,我们要求最大的𝑓(𝑎)的子序列,所以随意删减,但是没办法增加,所以当 i > ai 的时候,我们可以将 i 减小,但如果是 ai > i的话,我们无法将i增大。
所以我们需要考虑的是什么呢,是怎么删除减少让符合的最多,所以我们需要删除的数量,从小到大来转移。每次记录删除数字前面符合的索引个数,然后加上当前的的,来更新后面的最大值。利用树状数组,来维护最大值。即可
代码:
/*Looking! The blitz loop this planet to search way
Only my RAILGUN can shoot it 今すぐ
身体中を 光の速さで
駆け巡った確かな予感
掴め! 望むものなら残さず
輝ける自分らしさで
信じてるよ あの日の誓いを
この瞳に光る涙それさえも 強さになるから
*/
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
using namespace::std;
typedef long long ll;
inline __int128 read(){
__int128 x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
inline void print(__int128 x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
namespace simpler{
template<const unsigned _Mod=INT32_MAX>
class modint{
protected:
int64_t _val;
typedef modint<_Mod> _mint;
friend inline _mint
__construct(_mint&& _res,int64_t _x){
_res._val=_x;
return _res;
}
template<class _Tp>friend _mint
__quickly_power(_mint _a,_Tp _b){
if(_b<=0)return 1;
_mint _res=1;
for(;(bool)_b;_b>>=1,_a*=_a)if(_b&1)_res*=_a;
return _res;
}
public:
modint():_val(0){}
template<class _Tp>modint(_Tp _x){
_val=((int64_t)_x%_Mod+_Mod)%_Mod;
}
template<class _Tp>explicit inline operator _Tp(){return (_Tp)_val;}
friend _mint operator+(const _mint& _a,const _mint& _b){
if(_a._val+_b._val>=_Mod)return __construct(_mint(),_a._val+_b._val-_Mod);
return __construct(_mint(),_a._val+_b._val);
}
inline _mint& operator+=(const _mint& _b){return *this=*this+_b;}
inline _mint& operator++(){return *this=*this+__construct(_mint(),1);}
inline _mint& operator++(int){
_mint _res=*this;*this=*this+__construct(_mint(),1);
return _res;
}//plus
friend _mint operator-(const _mint& _a,const _mint& _b){
if(_a._val-_b._val<0)return __construct(_mint(),_a._val-_b._val+_Mod);
return __construct(_mint(),_a._val-_b._val);
}
inline _mint& operator-=(const _mint& _b){return *this=*this-_b;}
inline _mint& operator--(){return *this=*this-__construct(_mint(),1);}
inline _mint& operator--(int){
_mint _res=*this;*this=*this-__construct(_mint(),1);
return _res;
}//minus
friend inline _mint
operator*(const _mint& _a,const _mint& _b){
return __construct(_mint(),_a._val*_b._val%_Mod);
}
inline _mint& operator*=(const _mint& _b){return *this=*this*_b;}//multiplies
_mint operator-(){return __construct(_mint(),_val?_Mod-_val:_val);}//negative
friend inline _mint
operator%(const _mint& _a,const _mint& _b){
return __construct(_mint(),_a._val%_b._val);
}
inline _mint& operator%=(const _mint& _b){return *this=*this%_b;}//modulus
friend inline bool
operator==(const _mint& _a,const _mint& _b){
return _a._val==_b._val;
}
friend inline bool
operator!=(const _mint& _a,const _mint& _b){
return _a._val!=_b._val;
}
friend inline bool
operator<(const _mint& _a,const _mint& _b){
return _a._val<_b._val;
}
friend inline bool
operator>(const _mint& _a,const _mint& _b){
return _a._val>_b._val;
}
friend inline bool
operator<=(const _mint& _a,const _mint& _b){
return _a._val<=_b._val;
}
friend inline bool
operator>=(const _mint& _a,const _mint& _b){
return _a._val>=_b._val;
}
friend inline _mint
operator&(const _mint& _a,const _mint& _b){
return _a._val&_b._val;
}
inline _mint& operator&=(const _mint& _b){return *this=*this&_b;}
friend inline _mint
operator|(const _mint& _a,const _mint& _b){
return _a._val|_b._val;
}
inline _mint& operator|=(const _mint& _b){return *this=*this|_b;}
friend inline _mint
operator^(const _mint& _a,const _mint& _b){
return _a._val^_b._val;
}
inline _mint& operator^=(const _mint& _b){return *this=*this^_b;}
friend inline _mint
operator<<(const _mint& _a,const _mint& _b){
return _a._val<<_b._val;
}
inline _mint& operator<<=(const _mint& _b){return *this=*this<<_b;}
friend inline _mint
operator>>(const _mint& _a,const _mint& _b){
return _a._val>>_b._val;
}
inline _mint& operator>>=(const _mint& _b){return *this=*this>>_b;}
inline _mint operator~()const{return __construct(_mint(),~_val);}
inline bool operator!()const{return !_val;}
friend inline std::istream&
operator>>(std::istream& _is,_mint& _b){
return _is>>_b._val;
}
friend inline std::ostream&
operator<<(std::ostream& _os,const _mint& _b){
return _os<<_b._val;
}
template<class _Tp>_mint
power(_Tp _n)const{
return __quickly_power(*this,_n);
}
inline _mint inv()const{return __quickly_power(*this,_Mod-2);}
friend inline _mint
operator/(const _mint& _a,const _mint& _b){
return __construct(_mint(),_a._val*_b.inv()._val%_Mod);
}
inline _mint& operator/=(const _mint& _b){return *this=*this/_b;}
};//modint 2.0
}
using mint=simpler::modint<998244353>;
const int Maxn=1e5+5;
//definition
//mint a[Maxn];
//mint f[2][Maxn];
int n;
ll lowbit(ll x){
return x&-x;
}
ll tree[200005];
void add(int x,ll z){
for (int i =x; i<=200005; i+=lowbit(i)) {
tree[i]=max(tree[i], z);
}
}
ll gtsum(ll x){
ll an=0;
for (int i =x; i>0; i-=lowbit(i)) {
an=max(an, tree[i]);
}
return an;
}
int a[200005];
int main(){
ios::sync_with_stdio(false);
cin.tie(); cout.tie();
set<int>ff[200005];
cin>>n;
for (int i =1; i<=n; i++) {
cin>>a[i];
if (i>=a[i]) {
ff[i-a[i]].insert(a[i]);
}
}
ll jk;
for (int i =0; i<200005; i++) {
for(auto x:ff[i]){
jk=gtsum(x-1);
add(x, jk+1);
}
}
printf("%lld\n",gtsum(n));
return 0;
}