题目链接https://www.zhixincode.com/contest/8/problem/B?problem_id=123
题目大意:总共n个数,删除2个,要使删完之后连起来拼出的数字最大,输出这个连起来的结果
贪心题,直接想情况比较复杂,可以把删两次的过程看做两次独立的删除。
每次独立的删除中,肯定优先删除位数最小的数,再比较所有最小的数删除后剩余的数对答案的贡献,这里只要顺序两两比较最小位数的数删除后的结果。如果删除前面的数结果更优就结束这次删除,反之继续比较。
因为一旦前面的数删除比下一个结果更优,那么肯定在较高位比下一位要高,再往下删除的话,较高位已经定下来了,是没有可能再比前面的结果更优了。
删除l和r的时候 两者的区别只在于:
删L:[L+1,R]
删R:[L,R-1]
只要比较这个区间就可以了
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <random>
#include <cstring>
#include <chrono>
#include <cmath>
#include <stdlib.h>
#include <map>
#define LL long long
using namespace std;
const int maxn = 6e3 + 10;
int s[maxn * 10], t[maxn * 10];
int T, n, lenq, vis[maxn], da[maxn], len[maxn], nxt[maxn], lst[maxn];
/*
* 分两次删除处理,每次删除是一个独立的过程
* 在一次删除操作中,比较所有当前最短长度删除之后对答案产生的贡献
* */
void add(int *q, int x)//数组看作是一个整数,ai代表第i位的数
{
if (x)
{
add(q, x / 10);
q[++lenq] = x % 10;
}
}
int check(int l, int r)
{
//(l + 1, r) erase(l)
//(l, r - 1) erase(r)
lenq = 0;
for (int i = l + 1; i <= r; ++i)//删l
{
if (!vis[i]) add(s, da[i]);
}
lenq = 0;
for (int i = l; i < r; ++i)//删r
{
if (!vis[i]) add(t, da[i]);
}
for (int i = 1; i <= lenq; ++i)//比较删除两者的结果
{
if (s[i] > t[i]) return 1;
if (s[i] < t[i]) return 0;
}
return 0;
}
void erase()
{
int Minlen = 1 << 30, num = 0, p = -1;
for (int i = 1; i <= n; ++i)
{
if (vis[i])
{
continue;
}
Minlen = min(Minlen, len[i]);
}
for (int i = 1; i <= n; ++i)
{
if (vis[i] || len[i] > Minlen)
{
continue;
}
//所有最小长度的ai p记录最后一个最小长度的串的位置
++num; lst[i] = p; p = i;
}
nxt[p] = -1;
if (num == 1)//只有一个最小长度的串
{
vis[p] = 1;
return;
}
while (lst[p] != -1)
{
nxt[lst[p]] = p;
p = lst[p];
}
while (nxt[p] != -1)
{
if (check(p, nxt[p]))
{
vis[p] = 1;
return ;
}
p = nxt[p];
}
vis[p] = 1;
}
int main()
{
cin>>T;
for(int kase=1;kase<=T;kase++)
{
cin>>n;
for (int i = 1; i <= n; ++i)
{
vis[i] = 0, len[i] = 0;
}
for (int i = 1, x; i <= n; ++i)
{
cin>>da[i];
x = da[i];
while (x)
{
x /= 10;
++len[i];//记录ai的位数
}
}
erase(); erase();
cout<<"Case #"<<kase<<": ";
for (int i = 1; i <= n; ++i)
{
if (!vis[i])
{
cout<<da[i];
//cout<<"sss"<<endl;
}
}
cout<<endl;
}
return 0;
}