17.看楼房

目录

Description

Input

Output

Notes

思路

注意事项

C++完整代码(含详细注释)


Description

小张在暑假时间进行了暑期社会调查。调查的内容是楼房的颜色如何影响人们的心情。于是他找到了一个楼房从左到右排成一排的小区,这个小区一共有

n

栋楼房,每个楼房有一个颜色

c_i

和一个高度

h_i

。小张调查的内容为每次他站在第

i

栋楼和第

i+1

栋楼之间向左看,他记录下此时他看到的楼房颜色数作为他的调查结果。

由于小张在暑假时间沉迷游戏来不及做实地调查,只好拜托你将调查结果告诉他。

Input

本题有多组数据。

每组数据第一行一个整数

n

。表示有

n

栋楼房从左到右排成一排。

第二行

n

个数,表示每个楼房的颜色

(1 \leq c_i \leq 10^6 )

第三行

n

个数,表示每个楼房的高度

(1 \leq c_i \leq 10^9 )

数据保证所有组数据的

\sum{n} \leq 1000000

Output

每组数据输出

n

个数,第

i

个数表示他站在第

i

栋楼和第

i+1

栋楼之间向左看,能够看到的楼房颜色数。

Notes

在从左向右看楼房的时候,左边较矮的楼房会被右边较高的楼房挡住。


思路

使用两个栈,分别存储楼房的颜色和高度。

遍历楼房时,如果新入栈的楼房高度小于栈顶的楼房高度,则将新入栈的楼房的颜色和高度分别压入颜色栈和高度栈,并更新能够看到的楼房颜色数。

如果新入栈的楼房高度大于等于栈顶的楼房高度,则依次弹出栈顶的楼房,直到栈顶的楼房高度大于新入栈的楼房高度。

在每次弹出楼房时,如果弹出的是最后一个该颜色的楼房,则更新能够看到的楼房颜色数。最后,输出当前能够看到的楼房颜色数。


注意事项

  1. 代码中使用了两个栈来存储楼房的颜色和高度,确保栈顶元素始终是当前能够看到的最高楼房。
  2. 使用一个数组 c_class 来记录每种颜色的楼房数量,方便判断是否是新的颜色。
  3. 在每次入栈和出栈时,都需要更新 c_class 数组和 c_num 变量,以保证能够正确计算能够看到的楼房颜色数。
  4. 注意处理输入输出,使用 scanf 和 printf 来提高输入输出效率。
  5. 注意处理每组数据之间的换行符。

 

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;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

榆榆欸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值