51nod 2491贪心单调栈移掉K位数字

Posted SSL_ZZL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 2491贪心单调栈移掉K位数字相关的知识,希望对你有一定的参考价值。

移掉K位数字

51nod 2491 移掉K位数字


题目


输入样例

7
1432219
3

输出样例

1219

解题思路

可以发现越小的数在前面最后得到的数就越大
所以可以贪心,一直选更小的数在前面,最后得到一个递增序列
O(N ^ 2) 用单调栈优化

特殊处理
递增序列不够长:在做单调栈的时候用一个变量标记删了几个数,删够了就直接退出
前导零:这个很容易标记,注意略去前导零并不算删掉了数,不用补数
零:会出现最后只剩零的情况,会被上一步全部略去,特判输出0


Code

#include <bits/stdc++.h>
#define N 10002

using namespace std;

int n, m, top, shan, a[N + 100], v[N + 100], q[N + 100];

int main() 
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++) 
		char c = getchar();
		while(!(c >= '0' && c <= '9')) c = getchar();
		a[i] = c - '0';
	
	scanf("%d", &m);
	for(int i = 1; i <= n; i ++) 
		while(top && a[q[top]] > a[i] && shan < m) top --, shan ++;  //递增序列
		q[++ top] = i;
		if(shan == m) break;  //删的数够了直接退出
	
	for(int i = q[top] + 1; i <= n; i ++) q[++ top] = i;  //删够了但是后面该进栈的还没进
	for(int i = 1; i <= top; i ++) v[q[i]] = 1;   //标记留下的数
	while(shan < m)  //删的不够,就从后面往前删,因为前面更小留下来更优
		v[q[top]] = 0, top --, shan ++;
	int flag = 0;
	for(int i = 1; i <= n; i ++) 
		if(v[i] && a[i] > 0) flag = 1;  //标记前导零
		if(v[i] && flag) printf("%d", a[i]);
	
	if(!flag) printf("0");

以上是关于51nod 2491贪心单调栈移掉K位数字的主要内容,如果未能解决你的问题,请参考以下文章

402. 移掉 K 位数字-贪心

402. 移掉K位数字

Leetcode 402. 移掉K位数字

402. 移掉 K 位数字(中等)

LeetCode 0402. 移掉 K 位数字

402. 移掉 K 位数字