POJ3250-单调栈

Bad Hair Day
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 10988 Accepted: 3705

Description

Some of Farmer John's N cows (1 ≤ N ≤ 80,000) are having a bad hair day! Since each cow is self-conscious about her messy hairstyle, FJ wants to count the number of other cows that can see the top of other cows' heads.

Each cow i has a specified height hi (1 ≤ h≤ 1,000,000,000) and is standing in a line of cows all facing east (to the right in our diagrams). Therefore, cow i can see the tops of the heads of cows in front of her (namely cows i+1, i+2, and so on), for as long as these cows are strictly shorter than cow i.

Consider this example:

        =
=       =
=   -   =         Cows facing right -->
=   =   =
= - = = =
= = = = = =
1 2 3 4 5 6 

Cow#1 can see the hairstyle of cows #2, 3, 4
Cow#2 can see no cow's hairstyle
Cow#3 can see the hairstyle of cow #4
Cow#4 can see no cow's hairstyle
Cow#5 can see the hairstyle of cow 6
Cow#6 can see no cows at all!

Let ci denote the number of cows whose hairstyle is visible from cow i; please compute the sum of c1 through cN.For this example, the desired is answer 3 + 0 + 1 + 0 + 1 + 0 = 5.

Input

Line 1: The number of cows,  N
Lines 2..N+1: Line  i+1 contains a single integer that is the height of cow  i.

Output

Line 1: A single integer that is the sum of  c 1 through  cN.

Sample Input

6
10
3
7
4
12
2

Sample Output

5
题目大意:题目挺好懂的,就是数出右边比左边矮的牛的个数

最开始写了个双重循环,超时了

#include <iostream>
#define MAXN 80000
int N,height[MAXN+2];
int main()
{
	using namespace std;
	while(cin>>N)
	{
		for(int i=1;i<=N;++i)
			cin>>height[i];
		int ans=0;

		for(int i=1;i<=N;++i)
			for(int j=i+1;j<=N;++j)
				if(height[j]<height[i])
					++ans;
				else break;

			cout<<ans<<endl;
	}
	return 0;
}

然后本来就是查阅栈资料才找到这道题的,所以自然用栈来写了。仔细想了一下,自己想出了一个栈模拟,思路是这样的:

从后向前遍历高度数组,指标为i,将高度入栈,如果栈顶的高度小于现在i的高度,那么就一直出栈,直到栈空或者栈顶的高度比较小,此时出栈的个数就是此时的牛i所能看到的牛的数目,同时用vist将这个数字保存下来。下次如果牛i被出栈,那么那头牛看到的个数还得加上牛i看到的牛的个数。代码如下

#include <iostream>
#include <stack>
#include <cstring>
#define MAXN 80000
long long N,height[MAXN+2];
long long vist[MAXN+2];
int main()
{
	using namespace std;
	cin>>N;
	for(long long i=1;i<=N;++i)
		cin>>height[i];
	long long ans=0;  
	memset(vist,0,sizeof(vist));
	stack<long long>s;
	s.push(height[N]);
	for(int i=N-1;i>=1;--i)
	{
		if(!s.empty() && s.top()>=height[i])
			s.push(height[i]);
		else
		{
			long long temp=0;
			while (!s.empty() && s.top()<height[i])
			{
				if(vist[s.top()])
					temp+=vist[s.top()];
				++temp;
				s.pop();
			}
			ans+=temp;
			vist[height[i]]=temp;
			s.push(height[i]);
		}
	}		
	cout<<ans<<endl;
	return 0;
}

测试数据都过了,自己也测试了下是对的,结果一直RE,仔细一想,原来是那个牛怎么那么高啊,难怪RE,我得vist数组最大才80000,结果那些牛巨高,远远超过了我数组的大小,这样的话看来得换个方法。

然后自然而然的去看了一下别人的代码,原来别人是顺序遍历的,(我之前的思路是逆序)。当然这不是关键,关键是用栈的里储存的数目来替代那个vist,所以才需要顺序遍历,因此代码修改如下

11360988TSERROF3250Accepted2648K1204MSC++529B2013-03-17 18:56:51
#include <iostream>
#include <stack>
#include <cstring>
#define MAXN 80000
long long N,height[MAXN+2];
int main()
{
	using namespace std;
	while(cin>>N)
	{
		for(long long i=1;i<=N;++i)
			cin>>height[i];
		long long ans=0;  
		stack<long long>s;
		s.push(height[1]);
		for(int i=2;i<=N;++i)
		{
			while(!s.empty() && s.top()<=height[i])
				s.pop();
			if((!s.empty() && s.top()>height[i]) || s.empty())
			{
				ans+=s.size();
				s.push(height[i]);
			}
		}		
		cout<<ans<<endl;
	}	
	return 0;
}

如果用自己的栈的话

11361036TSERROF3250Accepted1488K688MSC++1578B2013-03-17 19:03:22
不过贡献了两次WA,首先我原来没写size函数,齐次我空间开小了,我把MAXSIZE改成了9w

#include <iostream>
//#include <stack>
#include <cstring>
#define MAXN 80000
long long N,height[MAXN+2];
#define MAXSIZE 90000
template<typename T>
class stack
{
private:
	T *STACK;
	long long TOP;
public:
	stack();
	~stack();
	bool pop();
	bool push(T);
	T top();
	bool empty();
	void show(bool);
	long long size();
};
template<typename T> stack<T>::stack()
{
	STACK=new T[MAXSIZE];
	TOP=-1;
}
template<typename T> stack<T>::~stack()
{
	delete STACK;
}
template<typename T> bool stack<T>::pop( )
{
	if(TOP==-1)
		return false;
	--TOP;
	return true;
}
template<typename T> bool  stack<T>::push(T d)
{
	if(TOP==MAXSIZE-1)return false;
	STACK[++TOP]=d;
	return true;
}
template<typename T>T  stack<T>::top()
{
	return STACK[TOP];
}
template<typename T> bool stack<T>::empty()
{
	if(TOP==-1)return true;
	return false;
}
template<typename T> void  stack<T>::show(bool reverse)
{
	if(reverse)
	{
		for(int i=TOP;i>=0;--i)
			std::cout<<STACK[i]<<" ";
	}
	else
	{
		for(int i=0;i<=TOP;++i)
			std::cout<<STACK[i]<<" ";
	}
}

template<typename T>long long stack<T>::size()
{
	return TOP+1;
}
int main()
{
	using namespace std;
	while(cin>>N)
	{
		for(long long i=1;i<=N;++i)
			cin>>height[i];
		long long ans=0;  
		stack<long long>s;
		s.push(height[1]);
		for(int i=2;i<=N;++i)
		{
			while(!s.empty() && s.top()<=height[i])
				s.pop();
			if((!s.empty() && s.top()>height[i]) || s.empty())
			{
				ans+=s.size();
				s.push(height[i]);
			}
		}		
		cout<<ans<<endl;
	}	
	return 0;
}
其实也完全没必要用long long,改成int后空间减小了不少
11361054TSERROF3250Accepted904K688MSC++1542B2013-03-17 19:05:52
#include <iostream>
//#include <stack>
#include <cstring>
#define MAXN 80000
int N,height[MAXN+2];
#define MAXSIZE 90000
template<typename T>
class stack
{
private:
	T *STACK;
	int TOP;
public:
	stack();
	~stack();
	bool pop();
	bool push(T);
	T top();
	bool empty();
	void show(bool);
	int size();
};
template<typename T> stack<T>::stack()
{
	STACK=new T[MAXSIZE];
	TOP=-1;
}
template<typename T> stack<T>::~stack()
{
	delete STACK;
}
template<typename T> bool stack<T>::pop( )
{
	if(TOP==-1)
		return false;
	--TOP;
	return true;
}
template<typename T> bool  stack<T>::push(T d)
{
	if(TOP==MAXSIZE-1)return false;
	STACK[++TOP]=d;
	return true;
}
template<typename T>T  stack<T>::top()
{
	return STACK[TOP];
}
template<typename T> bool stack<T>::empty()
{
	if(TOP==-1)return true;
	return false;
}
template<typename T> void  stack<T>::show(bool reverse)
{
	if(reverse)
	{
		for(int i=TOP;i>=0;--i)
			std::cout<<STACK[i]<<" ";
	}
	else
	{
		for(int i=0;i<=TOP;++i)
			std::cout<<STACK[i]<<" ";
	}
}

template<typename T>int stack<T>::size()
{
	return TOP+1;
}
int main()
{
	using namespace std;
	while(cin>>N)
	{
		for(int i=1;i<=N;++i)
			cin>>height[i];
		long long ans=0;  
		stack<int>s;
		s.push(height[1]);
		for(int i=2;i<=N;++i)
		{
			while(!s.empty() && s.top()<=height[i])
				s.pop();
			if((!s.empty() && s.top()>height[i]) || s.empty())
			{
				ans+=s.size();
				s.push(height[i]);
			}
		}		
		cout<<ans<<endl;
	}	
	return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值