牛客练习赛69 E 字串(哈希)

题目链接

题目大意

给出一个长度为n排列p

规定一个区间 [l,r] (l<=r) 是 fair 的,当且仅当区间中最小值等于 l 并且最大值等于 r

求 fair 区间的个数

题目思路

我不会正解

首先把每一个i值映射成\(base^i\)

遍历一边全排列

然后每次加上base[a[i]]减去base[i],求贡献,如果[l,r]满足条件,那么这一段区间的add值为0,

有点口胡,建议自己多多理解

注意要写mp[0]=1

ps:有大佬用随机数异或+异或前缀和是真的秀

代码

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#define fi first
#define se second
#define debug printf(" I am here\n");
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=1e6+5,inf=0x3f3f3f3f;
const ull mod=1e9+7;
const double eps=1e-10;
ull base[maxn];
int n,a[maxn];
unordered_map<ull,int> mp;
signed main(){
    base[0]=1;
    for(int i=1;i<=1e6;i++){
        base[i]=base[i-1]*mod;
    }
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    ll ans=0;
    mp[0]=1;
    ull add=0;
    for(int i=1;i<=n;i++){
        add=(ull)(add+base[a[i]]-base[i]);
        ans+=mp[add];
        mp[add]++;
    }
    printf("%lld\n",ans);
    return 0;
}
posted @ 2020-09-25 17:14  hunxuewangzi  阅读(187)  评论(2编辑  收藏  举报