【Codeforces gym102890M】Mathematics society problem | 贪心

题目链接:原题连接

题目大意:

给出一个数字串,由 1 − 9 1-9 19组成,之后给出对于每个数字 1 ≤ i ≤ 9 1\le i \le 9 1i9要删除的个数,问删除之后,能组成的最大的数是多少?

题目思路:

之前在其他 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 WA17,仔细考虑一下,对于一个数字 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
***/

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/112797609
今日推荐