题目链接:原题连接
题目大意:
给出一个数字串,由 1 − 9 1-9 1−9组成,之后给出对于每个数字 1 ≤ i ≤ 9 1\le i \le 9 1≤i≤9要删除的个数,问删除之后,能组成的最大的数是多少?
题目思路:
之前在其他 o j oj oj做过一道类似的原题,原题是:
给出一个数字串,删除 m m m个数字之后,使得剩下的数字组成的数最大
这样看这道题的话,只需要考虑决策性就可以了。假设一个位置 i i i,是可以删除的,它必然满足 s i < s i + 1 s_i < s_{i+1} si<si+1,这样 s i s_i si删除之后,会让 s i + 1 s_{i+1} si+1取代使得这个位置的权值变大,所以只需要从前向后模拟就可以了。
如果删除完成,还有剩余的删除机会,那么对于最终序列来说,必然是单调不递增的了,此时删除前面的数只会造成更 不优
,所以此时从后向前删除就可以了。
那么对于这道题如何去考虑呢?
首先,拿到题第一眼思路就是仿照上面的思路,因为加了限制,所以只需要判断该位要删除的时候,可不可以删除就可以了。那么最后序列的样子必然是:
- 如果 s i < s i + 1 s_i < s_{i+1} si<si+1,那么 s i s_i si一定是没法删除的
- 否则 s i > s i + 1 s_i > s_{i+1} si>si+1,一定满足
写完之后, W A — — 17 WA——17 WA——17,仔细考虑一下,对于一个数字 x x x,他比其之前的大,就会把之前的给删除掉,但是如果最后这个数字是必须要删除的,那么这个数字可能就把比其后面一位大的给消除掉了。
例如:
38978 38978 38978 —— 8 8 8要删除 1 1 1次, 9 9 9要删除 1 1 1次
按照咱们的模拟,当 9 9 9来时,会把 8 8 8扔掉,最后删除9
得到: 378 378 378
其实可以得到: 387 387 387
因为 9 9 9一定是要扔掉的,但是他却把最优解扔掉了,所以这时只需要特判一下哪些数是一定要扔掉的,不需要用它扔掉前面的数。
所以加个特判就好了。
Code:
/*** keep hungry and calm CoolGuang! ***/
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17+7;
const ll maxn = 1e7+700;
const ll mod= 998244353;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){
char c=getchar();T x=0,f=1;while(!isdigit(c)){
if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
char s[maxn];
char st[maxn];
int top = 0;
int up[15],cop[15];
int vis[maxn];
int main(){
scanf("%s",s+1);
for(int i=1;i<=9;i++) scanf("%d",&up[i]);
n = strlen(s+1);
for(int i=1;i<=n;i++) cop[s[i]-'0']++;
for(int i=1;i<=n;i++){
if(up[s[i]-'0'] == cop[s[i]-'0']){
cop[s[i]-'0']--;
up[s[i]-'0']--;
continue;
}
while(top && up[st[top]-'0'] && s[i] > st[top]){
up[st[top]-'0']--;
top--;
}
st[++top] = s[i];
cop[st[top]-'0']--;
}
for(int k=1;k<=top;k++)
printf("%c",st[k]);
printf("\n");
return 0;
}
/***
12152
1 1 0 0 0 0 0 0 0
1 2 3 4 5 6 7 8 9
***/