题意
给出一个长度为n的数字串, 要求删去d个数字, 使得剩下的总数字最大 (1 ≤ d < n ≤ 10^5 )
思路
根据贪心策略, 越高位的数字越大越好.
但取高位数字时同时要保证剩余量能够满足一共选出n-d个数字
考虑到用优先队列
但同时要记录下刚才取出的数字所在位置, 每次把队列中位置在上次选出数字所在位置之前的元素弹出
AC代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
#define mst(a) memset(a, 0, sizeof(a))
using namespace std;
const int maxn = 1e5+10;
struct Node
{
int v, pos;
bool operator < (const Node& node) const { //定义优先队列的排序方式
return v < node.v || (v == node.v && pos > node.pos);
}
}p[maxn];
string s;
priority_queue<Node> que;
int a, b, c, mrk; //mrk用于记录目前出队卡到第几位
void init(){
while( que.size() ){ que.pop(); }
mrk = 0;
s = "";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
while( cin >> a >> b && a )
{
init();
string ss = "";
b = a - b; //b定义改为剩余多少数字
cin >> s;
for( int i = 0; i < a; i++ ){
p[i].v = s[i] - '0';
p[i].pos = i;
if( i <= a - b ) que.push(p[i]);
}
int mrk = -1;
int i = a - b;
//cout << "size:" << que.size() << endl;
while( b ){
while( que.top().pos < mrk ) que.pop();
//cout << que.top().v << endl;
char tmp = que.top().v + '0';
ss += tmp;
mrk = que.top().pos;
que.pop();
if( i < a ) que.push(p[++i]);
b--;
}
cout << ss << endl;
}
return 0;
}
附
TLE代码 ( 一开始没考虑到时间复杂度的超时代码 )
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
#define mst(a) memset(a, 0, sizeof(a))
using namespace std;
const int maxn = 1e5+10;
string s;
typedef priority_queue<int> Q;
int a, b, c, mrk; //mrk用于记录目前出队卡到第几位
void init(){
//if( que.size() ){ que.empty(); }
mrk = 0;
s = "";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
while( cin >> a >> b && a )
{
init();
string ss = "";
b = a - b; //b定义改为剩余多少数字
cin >> s;
int len = s.size();
while( b-- ){
Q que;
int tmp;
map<int, int> mp;
//cout << mrk << ' ' << len-b << endl;
for( int i = mrk; i < len - b && i < len; i++ ){
tmp = s[i] - '0';
que.push(tmp);
if( !mp.count(tmp) ) mp.insert( make_pair(tmp, i) );
}
char a = que.top() + '0';
ss += a;
mrk = mp[que.top()]+1;
}
cout << ss << endl;
}
return 0;
}