【貪心】【字典樹】Gym - 101466A - Gaby And Addition

題意:定義一種無進位加法運算,給你n個正整數,問你取出兩個數,使得他們加起來和最大/最小是多少。spa

無進位加法運算,實際上是一種位運算,跟最大xor那個套路相似,很容易寫出對於每一個數字,其對應的最優數字是誰,就對於十叉的字典樹,貪心地儘可能往使結果更優越的方向走便可。blog

#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;
}
相關文章
相關標籤/搜索