Developing School's Contest 2012-2 by HUT:数字游戏

Problem Description

小艾和小牛在上数学课的时候觉得非常的无聊,于是他们想出了一个新的游戏,小牛写下N位的数字,小艾的任务
就是在去除了K位后得到一个最大的数。

Input

输入有多组数据。第一行输入一个N和一个K( 1 <= K < N <= 500 000 ).
接下来就是N位数字,确保输入数据中没有前导0。

Output

输出去除了K位后的最大数字。

Sample Input

4 2
1924
7 3
1231234
10 4
4177252841

Sample Output

94
3234
775841

Source

2012暑假集训

    //昨天做的hut(湖南工业吧)挂的一个比赛!感觉题目还是可以的。切了3到水模拟和4道思维题。还有4道太难了
都没人动。感觉这套题里面的思维题很有Topcode的味道,前提是在紧张的时间内做。
    //本题就是数字思维题!要想去掉k位数字后得到的数字最大,就要使序列中较大的数字尽量往左移(但并不是
单纯的去掉序列中最小的k位,如6189921569这样10位数去掉5位得到的最大值是99569而不是单纯去掉最小k位
后的89969)。所以就当前num[i]而言我们要去掉前面所有比他小的数字最好,而后面的暂时不管。
 以 4177252841为例,要想去掉4个数后得到最大值,从左往右看4、1是下降的,而7上升并且比4、1都大,
那么应该把4、1都 去掉这样7往左移两位整体数据就大了。继续往右扫描,7、2是下降的而到5(5前面有2更小)
就要把2去掉。后5、2、8中出现8比前面都大则要去掉前面小(从小到大去)的。最后满足k位即可。 
    所以本题可以利用优先队列维护当前num[i]前的序列,从i-n扫描每一位数,每次去掉num[i]前面比它小的数,
这样可以令序列一直处于单调递减状态,最后扫描完后如果还不到k维,则直接从队列中一位位去掉即可,
因为扫描完一遍后序列已经具有单调性。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
#define maxn 500050

struct node 
{
	int a,ti;
	friend bool operator<(node n1,node n2)
	{
		if(n1.a!=n2.a)	return n1.a>n2.a;
		else return n1.ti>n2.ti;
	}
};
char str[maxn];
int num[maxn];
bool used[maxn];

int main()
{
	int n,k,i,j;
	priority_queue<node>q;
	while(~scanf("%d%d",&n,&k))
	{
		while(!q.empty())
			q.pop();
		memset(used,false,sizeof(used));
		scanf("%s",str+1);
		for(i=1;i<=n;i++)
			num[i]=str[i]-'0';
		node tp,cnt;
		for(i=1;i<=n;i++)
		{
			while(k>0&&!q.empty()) //去掉前面比当前num[i]小的数
			{
				cnt=q.top();
				if(cnt.a<num[i])
				{
					q.pop();
					used[cnt.ti]=true;	
					k--;
				}
				else
					break;
			}
			tp.a=num[i],tp.ti=i;
			q.push(tp);
		}
		while(k>0&&!q.empty())
		{
			tp=q.top();
			q.pop();
			used[tp.ti]=true;
			k--;
		}
		for(i=1;i<=n;i++)
			if(!used[i])
				printf("%d",num[i]);
		puts("");
	}
	return 0;
}


你可能感兴趣的:(Developing School's Contest 2012-2 by HUT:数字游戏)