https://codeforces.com/problemset/problem/1175/F
艹,还能这么玩?
由于我们需要一段序列包含1-r-l+1,直接1-n随机一个ull数字b[i]
然后一段区间要是出现了子全排列,那么这段区间异或之和就是b[i]异或之和(加法之和应该也可以)
然后我们只要枚举每个1的两边,假设最大数字再右边(之后反着再来一遍),看一下r-mx+1这段区间是不是子全排列就行了
这题分治怎么做啊。。。不会啊。。。
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxl=3e5+10;
int n;ull ans;
int a[maxl];
ull b[maxl],pre[maxl],c[maxl];
mt19937 rnd(time(NULL));
inline void prework()
{
scanf("%d",&n);
ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);if(a[i]==1)++ans;
b[i]=rnd();
pre[i]=pre[i-1]^b[i];
}
}
inline void solv()
{
int mx,len;
for(int i=1;i<=n;i++)
if(a[i]==1)
{
mx=1;len=1;
for(int j=i-1;j>=0 && a[j]!=1;j--)
len++;
for(int j=i+1;j<=n && a[j]!=1;j++)
{
mx=max(a[j],mx);
if(mx>=j-i+1 && mx<=len+j-i && (c[j]^c[j-mx])==pre[mx])
++ans;
}
}
}
inline void mainwork()
{
for(int i=1;i<=n;i++)
c[i]=c[i-1]^b[a[i]];
solv();
reverse(a+1,a+1+n);
for(int i=1;i<=n;i++)
c[i]=c[i-1]^b[a[i]];
solv();
}
inline void print()
{
printf("%llu",ans);
}
int main()
{
prework();
mainwork();
print();
return 0;
}