F. The Number of Subpermutations 题解(异或hash维护全排列)

题目链接

题目思路

这种有关全排列的问题大多都是异或前缀和求解

所以我们可以枚举 1的位置。每次向左/右搜,往一个方向搜的时候记录扫到的最大值,当作排列的长度(最大

值),在判断这个子串是否合法就行了。

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=3e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
mt19937 rnd(time(0));
int n;
int a[maxn];
ll pre[maxn];
ll ha[maxn],base[maxn];
ll ans;
void cal(){
    for(int i=1;i<=n;i++){
        pre[i]=ha[a[i]]^pre[i-1];
    }
    for(int i=1,j=1;i<=n;i++){
        if(a[i]==1){
            j=1;
        }else{
            j=max(j,a[i]);
            if(i>=j&&(pre[i]^pre[i-j])==base[j]){
                ans++;
            }
        }
    }
}
signed main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        ha[i]=rnd();
        base[i]=(base[i-1]^ha[i]);
    }
    cal();
    reverse(a+1,a+1+n);
    cal();
    for(int i=1;i<=n;i++){
        if(a[i]==1) ans++;
    }
    printf("%lld\n",ans);
    return 0;
}
 
posted @ 2021-08-07 19:48  hunxuewangzi  阅读(72)  评论(0编辑  收藏  举报