1167E - レンジダブルポインタを削除します

問題の意味:[1、x]は、F(配列番号所与nおよびXの範囲を与え、その数nが L、R)は、削除された配列の数の[L、R]値として表現されますQがLのいくつかのペアがあり、R系列よう動作の非減少順
アイデア:[L、R]が成立する場合は、[L、R + 1]、 ...、[L、X] 確立され、そして[L、R]が成立する場合は、[L + 1、R]が成立していない、いかなる[L + 1、R-1が存在しない ] 設立され、それは、本問題が間隔単調ことがわかる、二重ポインタによって解決することができる
説明:\( T_I \)は右端Iの座標値を表し、\(S_Iが\) Iの左端の座標値を表し、
F(L、R)を確立するための3つの条件を満たしたときに
1 \(MAX(T_Lを、T_2、...、 T_L)<分(S_R、R&LT S_ {+}。1、.... s_x)\)
2. \(MAX(T_L、T_2、...、I-T_ {}。1)<S [I](1 <=私は= L <)\)
3. \(T_ {I} <分(S_ {I}。1 +、2 + S_ {I}、... s_x)(R&LT <= Iに<= X)\ )
あなたは、いくつかの前提条件が同様の接頭辞やアイデアで処理されている置くことができる場所、そしてあなたが直接ダブルポインタ適用することができます
参照:
https://www.cnblogs.com/henry-1202/p/10888691.htmlを(ギャングブログ)
https://baijiahao.baidu.com/s?id=1615129382322508344&wfr=spider&for=pc(ロス・バレーのダブルポインタの要約)
https://www.cnblogs.com/xyq0220/p/10875872.html

#include<bits/stdc++.h>
#define F first
#define S second
#define pii pair<int,int>
#define pb push_back
#define mkp make_pair
#define all(zzz) (zzz).being(),(zzz).end()
#define pii pair<long long ,int>
typedef long long ll;
typedef long long LL;
using namespace std;
const int maxn=1e6+7;
int s[maxn],t[maxn],ss[maxn],tt[maxn],a[maxn],precan[maxn],lastcan[maxn];
bool check(int l,int r){
    return precan[l-1]&&lastcan[r+1]&&ss[r+1]>tt[l-1];
}
int main(){
    int n,x;
    scanf("%d%d",&n,&x);
    memset(s,0x3f3f3f3f,sizeof(s));
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++){
        s[a[i]]=min(s[a[i]],i);
        t[a[i]]=max(t[a[i]],i);
    }
    
    long long  ans=0;
    for(int i=1;i<=x;i++){
        tt[i]=max(tt[i-1],t[i]);
    }
    ss[x+1]=0x3f3f3f3f;
    for(int i=x;i>=1;i--){
        ss[i]=min(ss[i+1],s[i]);
    }
    precan[0]=1;
    lastcan[x+1]=1;
    for(int i=1;i<=x;i++)precan[i]=precan[i-1]&&(tt[i-1]<s[i]);
    for(int i=x;i>=1;i--)lastcan[i]=lastcan[i+1]&&(ss[i+1]>t[i]);
    int r=1;
    for(int l=1;l<=x;l++){
        if(l>r)r++;
        while(r<x&&!check(l,r))r++;
        if(check(l,r))ans+=x-r+1;
    }
    cout<<ans<<endl;
    return 0;
}

おすすめ

転載: www.cnblogs.com/ttttttttrx/p/11204721.html