资源限制
时间限制: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
3 2 4 1
样例输出1
7
样例输入2
5
3 4 2 5 1
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 */