写不动数据结构了,下午打打D班的模拟赛玩玩。
题面:
小X穿越了,发现自己成为了一个小人,正准备为一位清朝王爷服务。只要好好地服务,王爷就有赏。
一开始,小X的赏赐是 a 0 a_0 a0,满足 0 ≤ a 0 ≤ 9 0\le a_0\le 9 0≤a0≤9。
小X将为王爷服务 n n n 次,第 i i i 次他有两种方式为王爷服务:
为王爷整理胡子。王爷会在原有赏赐的数字左侧添加一位,添加的数字为 a i a_i ai ( 0 ≤ a i ≤ 9 ) (0 \le a_i \le 9) (0≤ai≤9)
给王爷唱歌。王爷会在原有赏赐的数字右侧添加一位,添加的数字为 a i a_i ai。
小X想知道,他最终能获得的最多赏赐是多少。
输入格式
第一行一个整数 n n n,表示服务的次数。
第二行 n + 1 n+1 n+1 个 0 0 0 到 9 9 9 的整数,表示 a 0 , a 1 , a 2 , … , a n a_0,a_1,a_2,…,a_n a0,a1,a2,…,an。 ( n ≤ 1 0 6 ) (n\le 10^6) (n≤106)
保证a中不全为0。
输出格式
一个数,表示小X取得的最多赏赐。
样例
input
6
0 1 2 3 2 6 4
output
6321024
简化题意:
给定原数位,按顺序给原数补位,可以选择补在前或者补在后,求最后的数的最大值。
思路
考虑贪心和分治。
越靠左的位置越大数就越大,所以考虑对放左侧贪心。
最大且最靠右的一定得放最左,那它后面的数只能放右。
就递归按照这种方法处理前面的数,最后按顺序把数放在右侧即可。
加排序复杂度 O ( n log n ) O(n\log n) O(nlogn)。
注:千万不要让solve()
函数返回string
然后在中途为了图方便用substr()
分割,常数太大,且单次分割复杂度
O
(
n
)
O(n)
O(n),导致我挂了个点只有75分,用数组就好,数组常数小。
C o d e Code Code
struct node{
int id,v;
inline bool operator <(const node&w)const{
if(v==w.v)return id>w.id;
return v>w.v;
}
}o[1000006];
int n,t=1,a[1000006];
void solve(int r){
if(r<1)return;
while(o[t].id>r)t++;
int x=o[t].id;
printf("%d",a[x]);
solve(x-1);
for(int i=x+1;i<=r;i++)printf("%d",a[i]);
}
int main(){
n=read();
for(int i=1;i<=n+1;i++){
o[i]={i,a[i]=read()};
}
sort(o+1,o+2+n);
solve(n+1);
}