Codeforces 1175F The Number of Subpermutations (思维+rmq)

题意:

求区间[l, r]是一个1~r-l+1的排列的区间个数

n<=3e5

思路:

如果[l,r]是一个排列,首先这里面的数应该各不相同,然后max(l,r)应该等于r-l+1,这就能唯一确定这个区间满足条件了

我们只需要预处理出对于每个左端点,它能伸延到的最远的r,使得l到r各不相同,然后暴力

注意如果对于一次暴力不满足max(l,r)==r-l+1,那么此时r应该跳到l+max(r-l+1)-1,因为在这里才至少可能会满足条件

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional>
    
#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) 

using namespace std;

typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;

const db eps = 1e-6;
const int mod = 1e9+7;
const int maxn = 2e6+100;
const int maxm = 2e6+100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);
int a[maxn];
int d[maxn][25];
int n;
void init(){
    for(int i = 1; i <= n; i++) d[i][0] =a[i];
    for(int j = 1; (1<<j) <= n; j++){
        for(int i = 1; i + (1<<j) - 1 <= n; i++){
            d[i][j] = max(d[i][j-1], d[i + (1<<(j-1))][j-1]);
        }
    }
}
int rmq(int l, int r){
    int k = 0;
    while((1<<(k+1)) <= r-l+1)k++;
    return max(d[l][k], d[r-(1<<k)+1][k]);
}
int mx[maxn];
int id[maxn];
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        scanf("%d", &a[i]);
    }
    mx[n+1]=n;
    for(int i = n; i >= 1; i--){
        if(id[a[i]])mx[i]=min(mx[i+1],id[a[i]]-1);
        else mx[i]=mx[i+1];
        id[a[i]]=i;
    }
    init();
    int ans=0;
    for(int i = 1; i <= n; i++){
        int j = i;
        while(j<=mx[i]){
            //printf("%d %d %d\n",i,j,rmq(i,j));
            if(rmq(i,j)==j-i+1){ans++;j++;}
            else j=i+rmq(i,j)-1;
        }
    }
    printf("%d",ans);
    return 0;
}

 

posted @ 2019-06-07 14:36  wrjlinkkkkkk  阅读(573)  评论(0编辑  收藏  举报