数据结构优题(1)

Psychos in a Line CodeForces - 320D

算法:单调栈,模拟
注释:

  • 单调栈是寻找当前数字某一方向(左边或右边)第一个比起大(或者小)的数字。
  • 利用单调栈找到当前数左边第一个比其大的数。到达当前数时,保留在栈中的数字一定是非单调递减的数字,即未能被杀死的人;从栈中弹出的人为可以被当前这个人所能杀死的人。因为一个人可以同时杀死他人和被他人杀死,所以一列单调递减的数字,可以看做最前面的人可一次性杀死到单调递减最后一个人。
  • 利用ans[a[i]]数组保存第i个人a[i]所能杀死最多的人所需要的步数。
#include<iostream>
#include<cstdio>
#include<stack>
#define N 100010
using namespace std;
int a[N],ans[N];
stack<int>s;
int max(int a,int b)
{
	return a>b?a:b;
 } 
int main()
{
	int n,i;
	cin>>n;
	for(i=1;i<=n;i++)
	cin>>a[i];
	
	for(i=n;i>=1;i--)
	{
		if(s.empty())
		{
			ans[a[i]]=0;
			s.push(a[i]);
			continue;
		}
		
		if(a[i]<s.top())
		{
			s.push(a[i]);
			ans[a[i]]=0;
		}
		else if(a[i]>s.top())
		{
			int temp=max(1,ans[s.top()]);
			s.pop();
			while(!s.empty()&&a[i]>s.top())
			{
				temp=max(temp+1,ans[s.top()]);//其实就是找它前面的人杀人所需最多的步数 ,但是至少也得每次加1
				s.pop();
			}
			ans[a[i]]=temp;
			s.push(a[i]);
		}
	}
	
	int maxx=0;
	for(i=1;i<=n;i++)
	maxx=max(maxx,ans[i]);
	cout<<maxx;
	return 0;
}

Report Codeforces - 631C

算法:单调栈,模拟
注释:

  • 单调栈的另一个作用就是再将整个数列遍历完成之后,储存一个包含最后一个数字的单调递减(或递增)序列。
#include<iostream>
#include<cstdio>
#include<algorithm> 
#include<stack>
#define N 200010
using namespace std;
struct manager{
	int r,t;
}b[N];
int a[N],top,temp[N],f,h;
manager s[N];
int main()
{
	int n,m,i,j;
	manager res;
	
	cin>>n>>m;
	for(i=1;i<=n;i++)
	{
		cin>>a[i];
		temp[i]=a[i];
	}
	for(i=1;i<=m;i++)
	{
		cin>>res.t>>res.r;
		if(!top)s[++top]=res;
		else 
		{
			while(top!=0&&res.r>=s[top].r)
				top--;
			s[++top]=res;
		}
	}
	f=1;
	h=s[1].r;
	sort(temp+1,temp+h+1);
	
	for(i=2;i<=top;i++)
	{
		//cout<<s[i].r<<endl;
		for(j=s[i-1].r;j>s[i].r;j--)
		{
			//cout<<a[j]<<" "<<temp[f]<<endl;
			if(s[i-1].t==1)a[j]=temp[h--];
			else if(s[i-1].t==2)a[j]=temp[f++];
		}
	}
	
	for(i=1;i<=s[top].r;i++)
		if(s[top].t==1)a[i]=temp[f++];
		else if(s[top].t==2)a[i]=temp[h--];
	for(int i=1;i<=n;i++)
	cout<<a[i]<<" ";
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

601tyl

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

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

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

打赏作者

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

抵扣说明:

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

余额充值