题目描述
小明这些天一直在思考这样一个奇怪而有趣的问题:
在 1 ~ NN 的某个全排列中有多少个连号区间呢?
这里所说的连号区间的定义是:
如果区间 [L,R][L,R] 里的所有元素(即此排列的第 LL 个到第 RR 个元素)递增排序后能得到一个长度为 R−L+1R−L+1 的"连续"数列,则称这个区间连号区间。
当 NN 很小的时候,小明可以很快地算出答案,但是当 NN 变大的时候,问题就不是那么简单了,现在小明需要你的帮助。
输入描述
第一行是一个正整数 N(1≤N≤50×104)N(1≤N≤50×104), 表示全排列的规模。
第二行是 NN 个不同的数字 Pi (1≤Pi≤N)Pi (1≤Pi≤N),表示这 NN 个数字的某一全排列。
输出描述
输出一个整数,表示不同连号区间的数目。
输入输出样例
示例
输入
4
3 2 4 1
输出
7
代码:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int N;
scanf("%d", &N); // 读取输入的整数 N,表示数组 num 的长度
int sum = N; // 初始化 sum 为 N,因为每个单独的数字本身也是一个连号区间
int num[500000]; // 声明一个整型数组 num,用来存储输入的数字序列,长度最大为 500000
// 依次读取 N 个数字到数组 num 中
for (int i = 1; i <= N; i++) {
scanf("%d", &num[i]);
}
// 外层循环遍历数组 num,以每个元素作为连号区间的起始点
for (int j = 1; j <= N; j++) {
int max, min;
max = min = num[j]; // 初始化 max 和 min 为当前元素 num[j]
// 内层循环从当前元素的下一个位置开始遍历到数组末尾
for (int x = j + 1; x <= N; x++) {
if (num[x] > max) // 更新区间内的最大值
max = num[x];
if (num[x] < min) // 更新区间内的最小值
min = num[x];
// 如果当前子数组 num[j] 到 num[x] 是连号区间,则更新 sum
if ((max - min) == (x - j))
sum++;
}
}
// 输出最终结果 sum,表示所有连号区间的数量
printf("%d", sum);
return 0;
}