题意:
求区间[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 ",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; }