<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">【题目大意】</span>
现给定一个n位的整数,要求从其中删去k个数,使得删完后得到的数最大。
【样例输入】
5 2
25158
【样例输出】
558
【数据范围】
1≤k≤nxi
-----------------------------------------------------------------------------------------------------
【分析】
非常经典的贪心:删去第一个递减区域的最后一个元素。
#include<cstdio>
const int mn = 500000 + 5;
char num[mn];
int h[mn];
int main()
{
freopen("game.in", "r" , stdin);
freopen("game.out", "w", stdout);
int n, m, i, j, k;
scanf("%d%d", &n, &m);
scanf("%s", num + 1);
for(i = 1; i <= n; i++)
h[i] = num[i] - '0';
for(i = 1; i <= m; i++)
{
for(j = 1; j <= n; j++)
{
if(h[j] != 10)
{
for(k = j - 1; k > 0 && h[k] == 10; k--);
if(k && h[j] > h[k])
{
h[k] = 10;
break;
}
}
if(j == n)
{
for(; h[j] == 10; j--);
h[j] = 10;
break;
}
}
}
for(i = 1; i <= n; i++)
{
if(h[i] < 10)
printf("%d", h[i]);
}
}
上述方法的时间复杂度为O(mn^2)。再看看这道题的数据规模……唉,说起来都是满脸的泪啊!
-------------------------------------------------------------------
细细分析,我们可以发现,上面的代码将很多地方重复遍历了很多遍。那能不能不遍历那些地方?此时,我们可以用一个栈来优化:
1、依次将每个数压入栈。
2、每次压入栈之前,比较栈顶元素和压人元素。
如果栈顶≥压入,执行1
否则,将栈顶弹出,继续比较。
3、输出前n-k个数
按此法优化的代码的时间复杂度为O(n) (^_^+)。
#include<cstdio>
const int mn = 500000 + 5;
char num[mn];
int h[mn], ans[mn];
int main()
{
freopen("game.in", "r" , stdin);
freopen("game.out", "w", stdout);
int n, m, i, sum = 0;
scanf("%d%d", &n, &m);
scanf("%s", num + 1);
for(i = 1; i <= n; i++)
h[i] = num[i] - '0';
int top;
ans[1] = h[1];
for(i = 2, top = 1; i <= n && sum < m; i++)
{
while(ans[top] < h[i] && top && sum < m)
{
ans[top] = 0;
top--, sum++;
}
top++;
ans[top] = h[i];
}
for(top++; i <= n; i++, top++)
ans[top] = h[i];
if(!ans[1])
printf("0");
else
{
for(i = 1; i <= n - m; i++)
printf("%d", ans[i]);
}
}