【贪心】【字典树】Gym - 101466A - Gaby And Addition

题意:定义一种无进位加法运算,给你n个正整数,问你取出两个数,使得他们加起来和最大/最小是多少。

无进位加法运算,其实是一种位运算,跟最大xor那个套路类似,很容易写出对于每个数字,其对应的最优数字是谁,就对于十叉的字典树,贪心地尽量往使结果更优越的方向走即可。

#include<cstdio>
#include<algorithm>
using namespace std;
int ch[1000010*20][10],sz;
typedef long long ll;
ll pw[20];
void Insert(ll x)
{
int U=0;
for(int i=18;i>=0;--i){
if(!ch[U][x/pw[i]%10ll]){
ch[U][x/pw[i]%10ll]=++sz;
}
U=ch[U][x/pw[i]%10ll];
}
}
ll qmax(ll x){
int U=0;
ll res=0;
for(int i=18;i>=0;--i){
int wei=x/pw[i]%10ll;
int k=9;
for(int j=9-wei;j>=0;--j,--k){
if(ch[U][j]){
res+=(ll)k*pw[i];
wei=j;
goto OUT;
}
}
for(int j=9;j>9-wei;--j,--k){
if(ch[U][j]){
res+=(ll)k*pw[i];
wei=j;
goto OUT;
}
}
OUT:
U=ch[U][wei];
}
return res;
}
ll qmin(ll x){
int U=0;
ll res=0;
for(int i=18;i>=0;--i){
int wei=x/pw[i]%10ll;
int k=0;
for(int j=9-wei+1;j<=9;++j,++k){
if(ch[U][j]){
res+=(ll)k*pw[i];
wei=j;
goto OUT2;
}
}
for(int j=0;j<=9-wei;++j,++k){
if(ch[U][j]){
res+=(ll)k*pw[i];
wei=j;
goto OUT2;
}
}
OUT2:
U=ch[U][wei];
}
return res;
}
int n;
ll a[1000005];
int main(){
//freopen("a.in","r",stdin);
ll ans1=0,ans2=9000000000000000000ll;
pw[0]=1;
for(int i=1;i<=18;++i){
pw[i]=pw[i-1]*10ll;
}
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%I64d",&a[i]);
if(i>1){
ans1=max(ans1,qmax(a[i]));
ans2=min(ans2,qmin(a[i]));
}
Insert(a[i]);
}
printf("%I64d %I64d\n",ans2,ans1);
return 0;
}
上一篇:X230 安装 EI Capitan 10.11.5 总结


下一篇:ZOJ3874 Permutation Graph 【分治NTT】