小美创建图的方式则是:对于任意一个点对
,如果
是一对好的数字,则他会在
之间连上一条无向边。
现在小美想知道,他所创建出的图有多少个极大连通块。由于图中的边数过多他数不过来,因此他想请你帮他算一算。
每个测试文件均包含多组测试数据。第一行输入一个整数
代表数据组数,每组测试数据描述如下:
第一行输入一个整数
,表示数组 a 的长度。
第二行输入 n 个正整数
,表示数组。
除此之外,保证单个测试文件的
之和不超过
。
对于每组测试数据:
输出一行一个正整数表示他的图中连通块的个数。
2 4 3 3 4 6 5 1 2 3 4 5
2 5
import java.util.*;
// i-a[i] < j-a[j], i<j
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
while (t-- > 0) {
int n = in.nextInt();
int[] a = new int[n + 1];
int[] b = new int[n + 1];
for (int i = 1; i <= n; i++) {
a[i] = in.nextInt();
b[i] = i - a[i];
}
Deque<Integer> stack = new ArrayDeque<>(); // 单调栈:维护各个连通块最小值
for (int i = 1; i <= n; i++) {
int min = b[i];
while (!stack.isEmpty() && stack.peek() < b[i]) { // 可以合并前面的连通块
min = Math.min(min, stack.pop());
}
stack.push(min); // 只要连通块最小值<b[i],就可通过b[i]连边,合并前面的连通块
}
System.out.println(stack.size());
}
}
}