小张在暑假时间进行了暑期社会调查。调查的内容是楼房的颜色如何影响人们的心情。于是他找到了一个楼房从左到右排成一排的小区,这个小区一共有n栋楼房,每个楼房有一个颜色和一个高度。小张调查的内容为每次他站在第栋楼和第栋楼之间向左看,他记录下此时他看到的楼房颜色数作为他的调查结果。由于小张在暑假时间沉迷游戏来不及做实地调查,只好拜托你将调查结果告诉他。
解题思路:
题意要求站在i和i+1中间向左看,低的楼会被高的楼挡住,高的楼会露出颜色。
我们考察两个相邻的元素,如果左面比右面低,那么站在右面的楼的右面看,无论如何也看不到左面的楼,不会作为答案输出,因此我们可以将它舍弃,故保留下来的楼一定是单调递减的。
我们发现这个刚好属于单调栈的性质,因此从左到右遍历,每次统计单调栈中有多少中颜色,输出即可。
统计颜色的方法:记录一个颜色数组和当前有多少颜色 c,当单调栈中删除颜色时,若删除它导致颜色数组中对应的值等于零,则c减去一
代码:
#include<iostream>
#include<cstring>
using namespace std;
pair< int,int >st[1001010];
pair<int,int>a[1001010];
int v[1001010];
int tt;
int main(){
int t;
cin>>t;
while(t--){
int ans=0;
tt=0;
int n;
scanf("%d",&n);
for(int i=0;i<=n;i++)st[i].first=0,st[i].second=0;
for(int i=1;i<=n;i++)scanf("%d",&a[i].second); //颜色
for(int i=1;i<=n;i++) scanf("%d",&a[i].first); //高度
for(int i=1;i<=n;i++)
{
int x,y;
x=a[i].first;//gaodu
y=a[i].second;//yanse
while (tt && st[tt].first <= x) {
v[st[tt].second]--;
if(v[st[tt].second]==0)ans--;
tt -- ;
}
st[ ++ tt] = {x,y};
if(v[y]==0)ans++;
v[y]++;
printf("%d", ans);
if(i<n)printf(" ");
}
for(int i=0;i<=n;i++)v[st[i].second]=0;
puts("");
}
}