題解/算法 {F - Second Largest Query}

題解/算法 {F - Second Largest Query}

@LINK: https://atcoder.jp/contests/abc343/tasks/abc343_f;

錯誤: 用莫隊是會超時的; 因爲Add/Delete函數 你做不到O(1) 用平衡樹維護 他的時間是logN的; (通過了1/5的數據 其他都超時了);

錯誤: 用綫段樹套平衡樹 也會超時, 因爲Initialize的耗時是2e5 * logN * logN = 1e8量級 修改和查詢的耗時是logN*logN再乘上查詢次數 也是1e8量級 (通過了1/2數據);

之所以你會選擇樹套樹這種綫段樹, 你是犯了@LINK: https://editor.csdn.net/md/?articleId=126806166這個錯誤… 你認爲: 修改操作A[x]=d來更新數據域 所以數據域就必須維護區間裏的所有元素; 這種想法是錯誤的… 因爲非葉子節點的數據域 是通過Update_nonLeaf即兩個兒子的數據域來更新的 而不是通過A[x]=d這個修改操作來進行的!

因此 使用普通綫段樹 就可以了, 如果一時想不明白綫段樹的精髓 那麽你只需要去考慮 只要你能滿足Update_leaf, Update_nonLeaf這兩個函數 那麽這個綫段樹就是合理的! 其他的函數Initialize, Modify, Query都不用管他!!!

void Update_leaf( const __ArrayType_ & _val){ // 執行底層數組`Arr[i]==val` 更新葉子節點`[i,i]`對應的*數據域*;
    ASSERT_SYSTEM_( Interval.first == Interval.second);

    Ma = _val, Cont = 1;
    Ma1 = -1, Cont1 = 0;
}
void Update_nonLeaf( const __Data_ & _lef, const __Data_ & _rig){
    ASSERT_SYSTEM_( _lef.Interval.second+1 == _rig.Interval.first);

    Interval = {_lef.Interval.first, _rig.Interval.second};

    std::map< int, int> A;
    A[ _lef.Ma] += _lef.Cont;
    A[ _lef.Ma1] += _lef.Cont1;
    A[ _rig.Ma] += _rig.Cont;
    A[ _rig.Ma1] += _rig.Cont1;
    auto last = A.rbegin();  Ma = last->first;  Cont = last->second;
    ++ last;  Ma1 = last->first;  Cont1 = last->second;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值