洛谷CF982B 题解

本文介绍了如何使用STL中的优先队列解决竞赛编程问题,详细解析了暴力解法的不足,并通过代码示例展示了如何利用优先队列实现100分AC的解决方案。内容包括优先队列的基本概念、与普通队列的区别,以及在F1和F2子任务中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

谢谢管理员大大给过

优先队列速通大法

hello!我又来水体了,不过嘛,相对来说这道题普及-不算水。

那我们就来研究研究吧。

先看题目

题目传送门

F1:0分暴力

一开始我也是闲的没事想要弄一下暴力做法,结果令人悲伤。

啊哈,当然这个暴力肯定AC不了,然而再其它oj上有可能AC(我AC过),当然洛谷肯定不行哈,不然起不到学习的作用了。

给大家看一下暴力代码吧,也没什么好说的啦:

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
struct node{
	int x,y,z;
}; 
bool cmp(node x,node y)
{
	return x.x<y.x;
}
node w[200005];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>w[i].x;
		w[i].y=1;
		w[i].z=i;
	}
	sort(w+1,w+n+1,cmp);
	string s;
	cin>>s;
	for(int i=0;i<s.size();i++)
	{
		if(s[i]=='0')
		{
//			cout<<w[1].y<<endl;
			for(int j=1;j<=n;j++)
			{
				if(w[j].y==1)
				{
//					cout<<0<<" "<<j<<" "<<i<<endl;
					cout<<w[j].z<<" ";
					w[j].y=2;
//					cout<<w[j].y<<endl;
					break;
				}
			}
		}
		if(s[i]=='1')
		{
			for(int j=n;j>=1;j--)
			{
				if(w[j].y==2)
				{
					cout<<w[j].z<<" ";
					w[j].y=3;
					break;
				}
			}
		}
	}
	return 0;
}

好的,就是这样。

不过之后我就很烦恼,也不知道怎么用,我想着想着,就大喊了一句:“STL!我爱你!”。

大家应该也猜到了,我肯定又要厚颜无耻的使用STL速通大法了。

好言归正传,我们今天就来学习一下STL里的优先队列。

优先队列

这个不想map什么的,这个和队列差不多,队列就不讲了吧,不会的朋友可以上网搜一下。

那我们这里就主要讲一下优先队列和队列的区别。

首先优先队列优先队列,他的每一个数据都具有排序的优先顺序。而注意,和map,set不同的是他底部是堆的。

看一下优先队列的一些常用函数,和队列有一点区别o~

top 访问队头元素
empty 队列是否为空
size 返回队列内元素个数
push 插入元素到队尾 (并排序)
emplace 原地构造一个元素并插入队列
pop 弹出队头元素
swap 交换内容

然后看一下定义优先队列

priority_queue <int> q1;

这是最基本的。

priority_queue <int,vector<int>,greater<int> > q1;//从大到小
priority_queue <int,vector<int>,less<int> > q2;//从小到大

然后结构体,外配cmp函数
F1:

struct node{
   int x,y;
	friend bool operator<(node a,node b)
	{
   		return a.x<b.x;
	}
};
priority_queue<node> q;

F2:

struct node{
	int ans;
	int w;
};
struct cmp1{
	bool operator ()(node a,node b)
	{
		return a.w>b.w;
	}
};
priority_queue<node,vector<node>,cmp1> q;

果然vector和优先队列是STL里的好兄弟,定义都要一起

行了,就先讲这么多,剩下的去找dalao查一查吧

F2:100AC优先队列

我们的思路就是定义两个优先队列,一个存储内向(从小到大),一个存储外向(从大到小)。一开始将数据输入内向队列,接着每上车一个,就将内向队列顶部删除插入到外向中,接着外向遍历之后删除即可。具体看代码:

#include<iostream>
#include<string>
#include<queue>//队列头文件 
using namespace std;
struct node{//结构体 
	int ans;
	int w;
};
struct cmp1{//从大到小 
	bool operator ()(node a,node b)
	{
		return a.w>b.w;
	}
};
struct cmp2{//从小到大 
	bool operator ()(node a,node b)
	{
		return a.w<b.w;
	}
};
priority_queue <node,vector<node>,cmp1> q1;//内向 
priority_queue <node,vector<node>,cmp2> q2;//外向 
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int x;
		cin>>x;
		q1.push(node{i,x});//存储进入内向优先队列 
	}
	string a;//01字符串 
	cin>>a;
	for(int i=0;i<a.size();i++)
	{
		if(a[i]=='0')//如果内向 
		{
			if(!q1.empty())//其实这题不用,好习惯。 
			{
				cout<<q1.top().ans<<" ";//输出顶部id 
				q2.push(q1.top());//插入外向优先队列中 
				q1.pop();//删除 
			}
		}
		else
		{
			if(!q2.empty())//同上 
			{
				cout<<q2.top().ans<<" ";//输出顶部 
				q2.pop();//删除 
			}
		}
	}
	return 0;
}//就这么简单完毕! 

好的今天的题目讲解完了,你们学费了吗。
感谢大家耐心观看,刚开始写题解,写的不好,望大佬勿喷!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值