目录
Description
小张在暑假时间进行了暑期社会调查。调查的内容是楼房的颜色如何影响人们的心情。于是他找到了一个楼房从左到右排成一排的小区,这个小区一共有
栋楼房,每个楼房有一个颜色
和一个高度
。小张调查的内容为每次他站在第
栋楼和第
栋楼之间向左看,他记录下此时他看到的楼房颜色数作为他的调查结果。
由于小张在暑假时间沉迷游戏来不及做实地调查,只好拜托你将调查结果告诉他。
Input
本题有多组数据。
每组数据第一行一个整数
。表示有
栋楼房从左到右排成一排。
第二行
个数,表示每个楼房的颜色
。
第三行
个数,表示每个楼房的高度
。
数据保证所有组数据的
。
Output
每组数据输出
个数,第
个数表示他站在第
栋楼和第
栋楼之间向左看,能够看到的楼房颜色数。
Notes
在从左向右看楼房的时候,左边较矮的楼房会被右边较高的楼房挡住。
思路
使用两个栈,分别存储楼房的颜色和高度。
遍历楼房时,如果新入栈的楼房高度小于栈顶的楼房高度,则将新入栈的楼房的颜色和高度分别压入颜色栈和高度栈,并更新能够看到的楼房颜色数。
如果新入栈的楼房高度大于等于栈顶的楼房高度,则依次弹出栈顶的楼房,直到栈顶的楼房高度大于新入栈的楼房高度。
在每次弹出楼房时,如果弹出的是最后一个该颜色的楼房,则更新能够看到的楼房颜色数。最后,输出当前能够看到的楼房颜色数。
注意事项
- 代码中使用了两个栈来存储楼房的颜色和高度,确保栈顶元素始终是当前能够看到的最高楼房。
- 使用一个数组
c_class
来记录每种颜色的楼房数量,方便判断是否是新的颜色。 - 在每次入栈和出栈时,都需要更新
c_class
数组和c_num
变量,以保证能够正确计算能够看到的楼房颜色数。 - 注意处理输入输出,使用
scanf
和printf
来提高输入输出效率。 - 注意处理每组数据之间的换行符。
C++完整代码(含详细注释)
#include <iostream>
#include <vector>
#include <stack>
#include <cstdio>
using namespace std;
int main() {
int num;
cin >> num; // 读入数据组数
stack<int> stack_c, stack_h; // 用两个栈分别存储楼房的颜色和高度
while (num--) { // 循环处理每组数据
int n;
cin >> n; // 读入楼房的数量
stack_c = stack<int>(); // 清空颜色栈
stack_h = stack<int>(); // 清空高度栈
vector<long long> c_class(1000000, 0); // 用于记录每种颜色的楼房数量
vector<long long> c(n,0), h(n,0); // 分别存储楼房的颜色和高度
long long c_num = 0; // 记录能够看到的楼房颜色数
// 输入楼房颜色
for (int i = 0; i < n; i++) {
scanf("%lld", &c[i]);
}
// 输入楼房高度
for (int i = 0; i < n; i++) {
scanf("%lld", &h[i]);
}
// 遍历楼房
for (int i = 0; i < n; i++) {
if (stack_h.empty() || h[i] < stack_h.top()) { // 如果栈顶为空或者新入栈元素小于栈顶
stack_h.push(h[i]);
stack_c.push(c[i]);
if (++c_class[c[i]] == 1) c_num++; // 如果是新的颜色,则更新c_num
}
else if (stack_h.top() <= h[i]) { // 如果新入栈元素大于等于栈顶
while (!stack_h.empty() && stack_h.top() <= h[i]) { // 依次弹出栈顶元素,直到栈顶元素大于新入栈元素
if (--c_class[stack_c.top()] == 0) c_num--; // 如果弹出的是最后一个该颜色的楼房,则更新c_num
stack_h.pop();
stack_c.pop();
}
stack_h.push(h[i]);
stack_c.push(c[i]);
if (++c_class[c[i]] == 1) c_num++; // 如果是新的颜色,则更新c_num
}
printf("%lld%c", c_num, i == n - 1 ? '\n' : ' '); // 输出当前能够看到的楼房颜色数
}
}
return 0;
}