一、题目描述
Description
小张在暑假时间进行了暑期社会调查。调查的内容是楼房的颜色如何影响人们的心情。于是他找到了一个楼房从左到右排成一排的小区,这个小区一共有 n 栋楼房,每个楼房有一个颜色 c 和一个高度 h 。小张调查的内容为每次他站在第 i 栋楼和第 i+1 栋楼之间向左看,他记录下此时他看到的楼房颜色数作为他的调查结果。由于小张在暑假时间沉迷游戏来不及做实地调查,只好拜托你将调查结果告诉他。
Input
本题有多组数据。
每组数据第一行一个整数 n 。表示有 n 栋楼房从左到右排成一排。
第二行 n 个数,表示每个楼房的颜色(1≤ c ≤ 1e6)。
第三行 n 个数,表示每个楼房的高度(1≤ h ≤ 1e9)。
数据保证所有组数据的 Σn ≤ 1e6 。
Output
每组数据输出 n 个数,第 i 个数表示他站在第 i 栋楼和第 i+1 栋楼之间向左看,能够看到的楼房颜色数。Notes
在从左向右看楼房的时候,左边较矮的楼房会被右边较高的楼房挡住。
测试输入 期待的输出 时间限制 内存限制 额外进程 测试用例 1 以文本方式显示
- 2↵
- 5↵
- 1 2 3 4 5↵
- 1 3 4 2 5↵
- 5↵
- 1 2 4 4 5↵
- 1 3 4 2 5↵
以文本方式显示
- 1 1 1 2 1↵
- 1 1 1 1 1↵
1秒 64M 0
二、思路过程
小张的故事告诉我们,暑假不要过度沉迷游戏,以致于该做的作业都被落下。
小张的故事还警戒我们,就算自己的事情做不完,也不应该去麻烦一个陌生人,就好像我debug了一个上午,现在只想让小张退学。
可他竟然可以让程序设计的老师无偿帮他,有黑幕啊!
栈的基本应用。
这道题非常基础,入栈,出栈,取栈顶元素,等等。这是一道帮助新手(我)快速入门栈的简单题目。
我们需要让楼高入栈,确保从栈底到栈顶是递减的,栈内每一个元素就是我们在当前位置所能看到的每一栋楼房;在此基础上,统计这些楼房的颜色有几种,就是我们观察到的颜色数量。我们不关心一种颜色有多少个,但是我们关心的是有多少种颜色,非常适合采用“桶”。
三、代码实现
头文件
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
声明栈体(没什么好说的,就是书上的内容)
struct st {
int h[1000010],c[1000010];
int front = 0;
void push( int height , int color ) {
h [ front ] = height;
c [ front ] = color;
front++ ;
}
void pop() {
if ( front > 0 ) front-- ;
}
int toph() {
if ( front > 0 ) return h [ front-1 ];
}
int topc() {
if ( front > 0 ) return c [ front-1 ];
}
int size() {
return front;
}
};
在这样的一个栈里,有楼房的高度height和楼房的颜色color两个信息,它们作为一个整体共同放在栈顶。
对每一组数据:
int color_num = 0; //color_num用来计数。
int n;
scanf("%d",&n); //有n栋楼
struct st stack;
for ( int i=0 ; i<n ; i++ ) {
scanf( "%d" , & building_c[i] );
bucket_color[i+1] = 0;
//bucket_color[]指的是桶中的颜色。
//当bucket_color由0变为1时,color_num加1;当bucket_color由1变为0时,color_num减1
}
for ( int i=0 ; i<n ; i++ ) {
int building_h;
scanf( "%d" , & building_h );
//小元素出栈
while ( stack.size() && stack.toph() <= building_h ) {
bucket_color[ stack.topc() ] --;
if ( bucket_color[ stack.topc() ] == 0 ) color_num--;
stack.pop();
}
//新元素入栈
stack.push(building_h,building_c[i]);
//当元素出入栈时,对应的颜色数也要立刻变化
bucket_color[ stack.topc() ] ++;
if ( bucket_color[ stack.topc() ] == 1 ) color_num++;
if (i!=n-1) cout << color_num << ' ';
else cout << color_num << endl;
这里我还想补充一点:我一整个上午改来改去始终超时的原因竟然是——cin读入的速度比scanf慢!小细节决定大成败!虽然cin读入更加方便,但是当数据量庞大的时候,scanf是一个更好的选择。
四、完整代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
int building_c[N],bucket_color[N];
struct st {
int h[1000010],c[1000010];
int front = 0;
void push(int height,int color) {
h[ front ] = height;
c[ front ] = color;
front++;
}
void pop() {
if (front > 0) front--;
}
int toph() {
if (front > 0) return h[front-1];
}
int topc() {
if (front > 0) return c[front-1];
}
int size() {
return front;
}
};
int main(){
int m;
scanf("%d",&m); //有m组数据
for (int j=0;j<m;j++) {
int n;
scanf("%d",&n); //有n栋楼
struct st stack;
for (int i=0;i<n;i++) { scanf("%d",&building_c[i]); bucket_color[i+1] = 0; }
int color_num = 0;
for (int i=0;i<n;i++) {
int building_h;
scanf("%d",&building_h);
while ( stack.size() && stack.toph() <= building_h ) {
bucket_color[ stack.topc() ] --;
if ( bucket_color[ stack.topc() ] == 0 ) color_num--;
stack.pop();
}
stack.push(building_h,building_c[i]);
bucket_color[ stack.topc() ] ++;
if ( bucket_color[ stack.topc() ] == 1 ) color_num++;
if (i!=n-1) cout << color_num << ' ';
else cout << color_num << endl;
}
}
return 0;
}
总结:这道题目不难,目的是帮助新手快速入手栈的基本操作。