辉夜大小姐想让我构造不降序列 双指针+思维

辉夜大小姐想让我构造不降序列 双指针+思维

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
/*
题解:
首先得到 f(1,r) 的一个区间,然后容易得到 f(2,x) 这个x>r(这个可以自己思考一下)
所以就有点像双指针。
对于每一个区间 f(l,r),我都应该判断 l-1 之前的都是顺序的,r+1之后都是顺序的
并且最小的 (r+1,n) 的位置要大于最大的 (1,l-1) 这个位置
*/
int lc[maxn],rc[maxn],L[maxn],R[maxn],pre[maxn],last[maxn];
bool check(int x,int y){
    if(pre[x-1]&&last[y+1]&&L[y+1]>R[x-1]) return true;
    return false;
}
int main(){
    int n,x;
    scanf("%d%d",&n,&x);
    memset(L,inf,sizeof(L));
    memset(lc,inf,sizeof(lc));
    for(int i=1,v;i<=n;i++) {
        scanf("%d",&v);
        lc[v] = min(lc[v],i);
        rc[v] = max(rc[v],i);
    }
    for(int i=x;i>=1;i--){
        L[i] = min(L[i+1],lc[i]);
    }
    for(int i=1;i<=x;i++){
        R[i] = max(R[i-1],rc[i]);
    }
    pre[0] = 1;
    for(int i=1;i<=x;i++){
        pre[i] = pre[i-1]&(R[i-1]<lc[i]);
    }
    last[x+1] = 1;
    for(int i=x;i>=1;i--){
        last[i] = last[i+1]&(L[i+1]>rc[i]);
    }
    ll ans = 0;
    int now = 1;
    for(int i=1;i<=x;i++){
        while(now<i) now++;
        while(now<=x&&!check(i,now)) now++;
        if(check(i,now)) ans+= x - now + 1;
    }
    printf("%lld
", ans);
}
原文地址:https://www.cnblogs.com/EchoZQN/p/13957239.html