试题 历届试题 连号区间数

资源限制
时间限制:1.0s   内存限制:256.0MB
 
问题描述

小明这些天一直在思考这样一个奇怪而有趣的问题:

在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是:

如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。

当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。

输入格式

第一行是一个正整数N (1 <= N <= 50000), 表示全排列的规模。

第二行是N个不同的数字Pi(1 <= Pi <= N), 表示这N个数字的某一全排列。

输出格式

输出一个整数,表示不同连号区间的数目。

样例输入1
4
3 2 4 1
 
样例输出1
7
 
样例输入2
5
3 4 2 5 1
 
样例输出2
9
 
 
这题要是没注意到全排列的话估计会觉得挺麻烦的,我也没想通用并查集要怎么做,但是,题目中给出的N个数是1~N的某个全排列,也就是说,这1~N每个数都会且仅会出现一次,那么判断某个区间是否是连号区间的条件就简单了:若区间(i, j)里的最大值-最小值 = j-i,那就说明这是个连号区间. 可以直接暴力枚举.
 
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <string>
 6 #include <cmath>
 7 #include <algorithm>
 8 #define INF 0x3f3f3f3f
 9 #define zero 1e-7
10 
11 using namespace std;
12 typedef long long ll;
13 const ll mod=1e9+7;
14 const ll max_n=5e4+7;
15 
16 int a[max_n];
17 
18 int main() {
19     int n, ans=0;
20     cin>>n;
21     for(int i=0; i<n; i++) cin>>a[i];
22     for(int i=0; i<n; i++) {
23         int maxp=a[i];
24         int minp=a[i];
25         for(int j=i+1; j<n; j++) {//这里不考虑i=j的情况,因为单个数也算作一个连号区间,所以不必多作判断,直接在结果上加n就好了  
26             if(a[j]<minp) minp=a[j];
27             if(a[j]>maxp) maxp=a[j];
28             if(maxp-minp==j-i) ans++;
29         }
30     }
31     cout<<ans+n<<endl;
32      return 0;
33 }  
34 /*
35 7
36 1 3 6 5 4 7 2
37 
38 15
39 */ 
原文地址:https://www.cnblogs.com/wwqzbl/p/13566373.html