Codeforces Round #679 (Div. 2, based on Technocup 2021 Elimination Round 1) D. Shurikens
题目:https://codeforces.com/contest/1435/problem/D
共有n个物品,价值从1~n各一件,每个+可以放一个物品,每个- x要求取出已放物品价值最小的物品,而且改物品价值为x。问能不能找出一种合理的放法。
思路:
类似栈的思想,每次 '-' 对应取出栈顶元素,而栈顶要为栈的最小值,而且这个最小值为x。
他要求怎么取,我们就反过来对应怎么放就好。即栈保存当前可以放的位置,遇到 '-' 就把x值放到栈顶位置。
因为他每次只能取最小值出来,所以栈里面的位置对应放置的元素应该是从上往下递增的,所以我们可以维护出一个mx[pos]数组,表示当前
位置pos能放的元素要大于mx[pos],如果x要放pos位置而且x<=mx[pos],那么显然是不合法了。
因为栈顶元素都是比他下面的元素小的,所以下一个元素的mx用栈顶的mx来更新就好了。
#include<bits/stdc++.h> #include<ext/rope> //#include<hash_map> #define sd(x) scanf("%d",&x) #define lsd(x) scanf("%lld",&x) #define ms(x,y) memset(x,y,sizeof x) #define fu(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) #define all(a) a.begin(),a.end() using namespace std; using namespace __gnu_cxx; typedef long long ll; typedef unsigned long long ull; typedef long double ld; const int maxn=1e5+91; const int mod=1e9+7; const int INF=1e9+7; const double pi=acos(-1); int ans[maxn],mx[maxn]; int main() { std::ios::sync_with_stdio(false); std::cin.tie(0);//cout和printf不要不要不要连用!! //freopen("t.txt","r",stdin); int n;cin>>n; int st=0,k=0; bool ok=1; vector<int> ad;ad.clear(); fu(i,1,2*n) { char c;int x; cin>>c; if(c=='+') { k++; ad.push_back(k); //可以放的位置 } else { cin>>x; if(ad.empty()||!ok) { //栈空了说明减号多了,不合法 ok=0; continue; } st=ad.back(); ans[st]=x;//x放在st位置 ad.pop_back(); if(x<=mx[st]) //st位置的元素要大于mx[st], { ok=0; continue; } if(!ad.empty())//更新上一个位置的最小满足值 mx[ad.back()]=max(mx[ad.back()],x); } } if(!ok) puts("NO"); else { puts("YES"); fu(i,1,n) printf("%d ",ans[i]); printf("\n"); } return 0; }