Codeforce题解:Shurikens

题目链接:https://codeforces.com/contest/1413/problem/D

题干描述:

Tenten runs a weapon shop for ninjas. Today she is willing to sell n shurikens which cost 1, 2, …, n ryo (local currency). During a day, Tenten will place the shurikens onto the showcase, which is empty at the beginning of the day. Her job is fairly simple: sometimes Tenten places another shuriken (from the available shurikens) on the showcase, and sometimes a ninja comes in and buys a shuriken from the showcase. Since ninjas are thrifty, they always buy the cheapest shuriken from the showcase.

Tenten keeps a record for all events, and she ends up with a list of the following types of records:

  • ‘+’ means that she placed another shuriken on the showcase;
  • '- x’means that the shuriken of price x was bought.

Today was a lucky day, and all shurikens were bought. Now Tenten wonders if her list is consistent, and what could be a possible order of placing the shurikens on the showcase. Help her to find this out!

Input
The first line contains the only integer n (1≤n≤105) standing for the number of shurikens.

The following 2n lines describe the events in the format described above. It’s guaranteed that there are exactly n events of the first type, and each price from 1 to n occurs exactly once in the events of the second type.

Output
If the list is consistent, print “YES”. Otherwise (that is, if the list is contradictory and there is no valid order of shurikens placement), print “NO”.

In the first case the second line must contain n space-separated integers denoting the prices of shurikens in order they were placed. If there are multiple answers, print any.
Examples
Input

4
+
+
- 2
+
- 3
+
- 1
- 4

Output

YES
4 2 3 1 

Input

3
+
+
+
- 2
- 1
- 3

Output

NO

Note
In the first example Tenten first placed shurikens with prices 4 and 2. After this a customer came in and bought the cheapest shuriken which costed 2. Next, Tenten added a shuriken with price 3 on the showcase to the already placed 4-ryo. Then a new customer bought this 3-ryo shuriken. After this she added a 1-ryo shuriken. Finally, the last two customers bought shurikens 1 and 4, respectively. Note that the order [2,4,3,1] is also valid.

In the second example the first customer bought a shuriken before anything was placed, which is clearly impossible.

In the third example Tenten put all her shurikens onto the showcase, after which a customer came in and bought a shuriken with price 2. This is impossible since the shuriken was not the cheapest, we know that the 1-ryo shuriken was also there.

题意描述

一家店卖忍者用的手里剑(应该是手里剑)。每天有n把手里剑,每把剑的价格分别为1~n。店员不是一次性把所有手里剑都摆在柜台上,而是每次摆一把,分n次摆。我们不知道摆剑的顺序。
有忍者来买手里剑,他们每次只买当前摆在柜台上的手里剑中最便宜的一把。
问我们:题目中给出的2n个操作,是不是合理的。如果不合理,输出"NO";如果合理,输出"YES",并另起一行输出一行数列,表示店员放置手里剑的顺序(所有可能中的一种即可)。
关于操作的定义:
"+"表示,店员向柜台放了一把手里剑,至于放的是哪把我们不知道。
"- x"表示有忍者买走了价值为x的手里剑。
关于操作合理的定义:
当柜台为空时,忍者仍买走了一把手里剑,显然是不合理的。
当不能满足所有忍者都购买了当前柜台中最便宜的一把手里剑时,显然也不合理。

思路分析

我们可以确定的是,忍者只会买当前柜台中最便宜的一把手里剑。
也就是说当我们遇到"- x"操作时,x必然是当前柜台中最便宜的一把手里剑的价格,即当前柜台中的其他手里剑的价格都比x大。
但是有一个问题,我们根本没有办法确定,当前柜台中价格最低的手里剑是哪一把。因为"+"操作只能告诉我们,店员向柜台中放置了一把手里剑,但是没有告诉我们他放置的手里剑的价格。
那该怎么办呢?有一个想法是,我们根据顾客买的手里剑的价格来确定当前柜台中的手里剑的价格。
所以我们制定一个对我们最有利的规则:忍者买的手里剑总是柜台所有手里剑中最新拿上来的一把。也就是说,最新拿上来的一把就是当前柜台中价格最低的一把。再换句话说,柜员向柜台中摆剑的时候,一定要保证新摆的剑比当前柜台中所有的剑的价格都低!
那有朋友该纳闷了,店员凭啥这么摆啊?咱不是不知道店员摆的顺序吗?
我们之所以这么摆,是因为这样对我们最有利
正如我们所知道的,我们不知道店员摆手里剑的顺序。我们能做的只能是根据顾客买手里剑的顺序来反推操作是否可行。也就是说,只要对我们最有利的情况是可行的,那这个操作就是可行的。
那我们制定的规则最有利的依据是什么呢?我们在这道题中的限制就是,忍者只会买当前柜台中价格最低的一把手里剑。作为一名奸商 有智慧的商人,我摆的时候顺序一定会是n,n-1,……1.因为你不是总买最便宜的吗,那也就意味着越便宜的手里剑所受的限制就越少,那我当然是先把限制大的给卖出去。
但是我们能不能做到整个过程按照降序摆呢?不能。因为忍者买的时候给出了价格x,也就是说我们要想让操作合理,那就必须保证价格为x的我们已经摆进去了。别等着人家买了个价格为2的,你降序摆才摆到价格为4的。那对于我们来说最优解就是:**先摆贵的,并保证刚好在忍者要买价格为x的手里剑之前,把价值为x的手里剑摆上去。**我刚好在你要买之前把你想要的这个给摆上去。这就是我们的最有利的规则。

代码实现

相信大家也品出味了,刚摆的手里剑是最便宜的,而顾客只买最便宜的。也就是说,越先摆进柜台的就越晚出去。先进后出,这不就是个栈吗!现在写代码就很容易了。
代码如下:

#include
#include
using namespace std;
int n,ans[100005],x,num;
char ch;
stack v;
int main(){
	cin>>n;
	num=1;
	for(int i=1;i<=2*n;i++){
		cin>>ch;
		if(ch=='+'){
			v.push(num++);
			//如果是加的话,就代表向栈中添加元素,num表示这是第num个进栈的元素 
		}
		else{
			cin>>x;
			if(v.empty()) {
				//如果顾客要买手里剑时,柜台却空了,那显然是不合理的 
				cout<<"NO";
				return 0;
			}
			else if(x

我也是看到了codeforce上的题解才把这个题搞明白的。
第一次写题解,叙述有些啰嗦,大家包涵!
若有不足之处,还望指出!

你可能感兴趣的:(Codeforce题解,贪心算法,栈,acm竞赛)