51nod 1272 最大距离 (贪心或单调栈)

传送门51nod 1272



题目大意:从一组数中找出一对数,满足左边的数小于等于右边的数,求两数的最大距离。



思路

1.单调栈,建议学习一下单调栈的应用:单调栈原理及应用。理论上时间复杂度为O(n),但是实际没贪心快……并且最后一组会超时……迷思。不过还是给出单调栈的代码,大体思路是用一个单调递增栈处理,并用一个普通栈存储每次不能使栈单调的被弹出的元素。注意,我这里单调栈存储的是下标


2.贪心。先将数据记录位置和值,并从大到小排序。然后从小到大插入每个数,这样插入的数就保证了后面的比前面的大,而只需要记录出现的位置最小值,每次插入的时候记录当前的位置和最小位置之差的最大值就可以了。注意,如果两个元素值相同时要按照位置从小到大排序,否则会出错。



代码


单调栈(会超时)

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<stack>
using namespace std;

int main()
{
	int i,n,mx,top,a[50010];
	stack<int> st1,st2;
	scanf("%d",&n);	
	mx=0;
	for(i=0;i<n;i++) scanf("%d",&a[i]);
	for(i=0;i<n;i++)
	{
		//如果单调栈为空或当前元素大于栈顶元素则入栈 
		if(st1.empty()||a[i]<a[st1.top()]) st1.push(i);
		else
		{
			while(!st1.empty()&&a[i]>=a[st1.top()])
			{ //如果栈非空并且当前元素>=栈顶元素则将栈顶元素出栈 
				top=st1.top(); //栈顶元素 
				st2.push(top); //保存到 st2 普通栈 
				st1.pop();
				if(i-top>mx) mx=i-top; //记录最大距离 
			}
			st1.push(i); //将当前元素入栈 
			while(!st2.empty())
			{ //将普通栈中的元素再转移回单调栈 
				top=st2.top();
				st1.push(top);
				st2.pop();
			}
		}
	}
	printf("%d\n",mx);
	return 0;
}

贪心

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;

struct node
{
	int pos,val;
} a[50010];

int cmp(node x,node y)
{ //如果值相同按位置升序排列,否则按值升序排列 
	if(x.val==y.val) return x.pos<y.pos;
	else return x.val<y.val;
}

int main()
{
	int i,n,l,ans;
	scanf("%d",&n);
	ans=0;
	for(i=0;i<n;i++)
	{
		scanf("%d",&a[i].val);
		a[i].pos=i; //记录位置 
	}
	sort(a,a+n,cmp); //排序 
	ans=0;
	l=0x3f3f3f3f;
	for(i=0;i<n;i++)
	{ //插入每个元素 
		if(a[i].pos<l) l=a[i].pos; //记录最小位置 
		if(a[i].pos-l>ans) ans=a[i].pos-l; //记录最大距离 
	}
	printf("%d\n",ans);
	return 0;
}


  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值