题意:定义一种无进位加法运算,给你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 ",ans2,ans1); return 0; }