题意: 给定长度为N的0~9数字字符串,从中删掉D个字符,求能够构成的最大的数字。
思路:D个字符一个个的删,直到全部删完:
这样算下来,负责度就是O(N)。
例如:N=8,K=5, 序列为14231432。
步骤是每次选择出当前的最高位:
例如:
N=8,K=5, 序列为14231432。
/**
* 思路一: 双向链表
* Author:XXW
**/
#include
#include
#include
#include
#include
#include
using namespace std;
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
const int maxn = 1e5 + 5;
int N, D;
char str[maxn];
struct Node {
int prior, rear;
} nodes[maxn];
void del(int x) {
int a = nodes[x].prior;
int b = nodes[x].rear;
if(a == -1) {
nodes[b].prior = -1;
} else {
nodes[a].rear = b;
}
if(b == -1) {
nodes[a].rear = -1;
} else {
nodes[b].prior = a;
}
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
while(~scanf("%d %d", &N, &D) && N) {
scanf("%s", str);
nodes[0].prior = -1;
nodes[0].rear = 1;
nodes[N - 1].prior = N - 2;
nodes[N - 1].rear = -1;
for(int i = 1; i < N - 1; i++) {
nodes[i].prior = i - 1;
nodes[i].rear = i + 1;
}
int pos = 0, phead = 0, cnt = D;
while(cnt > 0) {
int np = nodes[pos].rear;
if(np != -1 && str[pos] < str[np]) {
del(pos);
if(pos == phead) phead = np;
pos = np;
cnt --;
} else if(np != -1 && str[pos] >= str[np]) {
pos ++;
continue;
} else if(np == -1) {
pos = nodes[pos].prior;
del(nodes[pos].rear);
cnt --;
}
int pp = nodes[pos].prior;
while(cnt > 0 && pp != -1 && str[pos] > str[pp]) {
del(pp);
pp = nodes[pos].prior;
cnt --;
}
if(pp == -1) phead = pos;
}
for(int i = 0, pos = phead; i < N - D; i ++) {
printf("%c", str[pos]);
pos = nodes[pos].rear;
}
puts("");
}
return 0;
}
/**
* 思路二: 线段树求区间最值
* Author:XXW
**/
#include
#include
#include
#include
#include
#include
using namespace std;
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
const int maxn = 1e5 + 5;
int N, D;
char str[maxn];
struct Node {
int prior, rear;
} nodes[maxn];
char segTree[maxn << 2];
int pos[maxn << 2];
void build(int l, int r, int rt) {
if(l == r) {
segTree[rt] = str[l];
pos[rt] = l;
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
if(segTree[rt << 1] >= segTree[rt << 1 | 1]) {
pos[rt] = pos[rt << 1];
} else {
pos[rt] = pos[rt << 1 | 1];
}
segTree[rt] = max(segTree[rt << 1], segTree[rt << 1 | 1]);
}
char ch;
int _prev;
char query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
if(ch < segTree[rt]) {
ch = segTree[rt];
_prev = pos[rt];
}
return segTree[rt];
}
int mid = (l + r) >> 1;
char ret = -1;
if(L <= mid) {
ret = max(ret, query(L, R, lson));
}
if(R > mid) {
ret = max(ret, query(L, R, rson));
}
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
while(~scanf("%d %d", &N, &D) && N) {
scanf("%s", str + 1);
D = N - D;
build(1, N, 1);
_prev = 0;
for(int i = 1; i <= D; i++) {
int l = _prev + 1, r = N - (D - i);
ch = -1;
char res = query(l, r, 1, N, 1);
printf("%c", res);
}
puts("");
}
return 0;
}