COMPFEST 13 - Finals Online Mirror (Unrated, ICPC Rules, Teams Preferred) L. Longest Array Deconstru

Problem - L - Codeforces 

 翻译:

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值