単調なスタックをいじり[解説]順列のCF1156E特別なセグメント

質問表面:http://codeforces.com/contest/1156/problem/E

Luogu翻訳:https://www.luogu.com.cn/problem/CF1156E

ドメイン名を変更するLuoguを言います

効果:長さN pの順列、必要な間隔の数[L、R]満足し、P [L] + P [R] =最大{P [I]}、L <= I <= Rを考えます

 

これは、デカルトの木であることを述べました。

しかし、私はしません

その後いじり。

第1の左の前処理[i]の位置の多数を、[i]をLと称します

R [i]は同様に右へ。

この要求は、単調スタックすることができます。

次に、LとRを列挙することができます。

しかし、明らかにそれが爆発します。

しかし、被験者に、あなたは片側のみを列挙することができます。

他の側へ直接アクセスすることはありません。

例えば、Lは、P [R] = PMAX-P [L]を列挙

唯一の右のそれには何のp [R]が存在しないことを知っています。

コードは以下の通りであります:

#include <ビット/ STDC ++ H>
 使用して 名前空間STDを、
const  int型 MAXN = 2 * 1E5 + 10 int型のn、[MAXN]、POS [MAXN]。
長い 長いANS;
INTをL [MAXN]、R [MAXN]は、[MAXN]です。
INT メイン()
{ 
    scanf関数(" %のD "、&N)
    以下のためにint型 i = 1 ; iが<= N; iが++ ){ 
        scanf関数(" %dを"[I])。
        POS [I] = I。
    } 
    int型のトップ=0 ;
    以下のためにint型 i = 1 ; iは= N <; iは++ ){
         一方(上部&& [S [トップ] <[I])をtop-- 
        L [I] =のS [トップ]。
        S [ ++トップ] = I。
    } 
    トップ = 0 ; S [トップ] = N + 1 以下のためにint型 I = N; I; i-- ){
         一方(上部&& [S [トップ] <[i])とtop-- 
        R [I] =のS [トップ]。
        S [ ++トップ] = I。
    } 
    のためのINT I = 1; iが<= N; iは++ ){
         場合(IL [I] <R [I] - I){
             ためINT J = L [I] + 1、J <I、J ++ 場合(POS [I] -a [J]]>私は、POSを[I] -a [J] <R [i])とANS ++ &&します
        } {
             ためのint型 J = I + 1、J <R [I]; J ++ 場合(POS [[I] -a [J] <私は、POSを&& [[I] -a [J]]> L [i])と++ ANS 
        } 
    } 
    のprintf(" %d個の\ n " 、ANS)。
    リターン 0 ; 
}

 

おすすめ

転載: www.cnblogs.com/ChrisKKK/p/11521144.html