origin : http://acm.bnu.edu.cn/v3/problem_show.php?pid=52723
from : CodeForcesGym
time limit : 6000 ms
memory limit : 1048576 KB
题意:求一串数中任意两数不进位相加的最小值和最大值
解法:对于每个数,建19位字典树,注意避免自相加即可
time used : 3213 ms
memory used : 947000 KB
Accepted :
#include <cstdio>
#include <algorithm>
#define constant const constexpr
typedef long long ll;
constant int maxN = 20e6 + 3;
constant ll maxNUM = 1e6 + 3;
int N,M;
int number[19];
ll num;
ll nums[maxNUM];
void reading()
{
std::scanf("%d",&N);
for (int i=0;i<N;++i) std::scanf("%I64d",nums+i);
}
void readin(int t)
{
num = nums[t];
for (int i=18;i>=0;--i)
{
ll t = num % 10LL;
number[i] = static_cast<int>(t);
num /= 10LL;
}
}
// Trie
int cnt;
struct node
{
int it;
int next[10];
int count;
node (int _it = -1):it(_it),count(0)
{
std::fill_n(next,10,-1);
}
};
node Trie[maxN];
void init()
{
cnt = 0;
}
void add(int t)
{
readin(t);
int i = 0, now = 0;
while (i < 19)
{
int t = number[i];
++Trie[now].count;
if (Trie[now].next[t] == -1) Trie[now].next[t] = ++cnt;
now = Trie[now].next[t];
Trie[now].it = t;
//std::printf("%d %d %d\n",i,t,now);
++i;
}
++Trie[now].count;
}
ll query_min()
{
//std::printf("Min Query:\n");
bool same_flag = true;
num = 0;
int i = 0, now = 0;
while (i < 19)
{
int t_it = number[i];
int t = (10-t_it)%10;
while (true)
{
int it_cnt = Trie[now].next[t];
if (it_cnt == -1) t = (t+1)%10;
else if ((Trie[it_cnt].count == 1) and (same_flag) and (Trie[it_cnt].it == t_it)) t = (t+1)%10;
else
{
if (Trie[it_cnt].it != t_it) same_flag = false;
num = 10LL*num+static_cast<ll>((t+t_it)%10);
now = it_cnt;
break;
}
}
//std::printf("%d %d %d %lld %d %d %d %d\n",i,t_it,t,num,same_flag,Trie[now].count,Trie[now].it,t_it);
++i;
}
return num;
}
ll query_max()
{
//std::printf("Max Query:\n");
bool same_flag = true;
num = 0;
int i = 0, now = 0;
while (i < 19)
{
int t_it = number[i];
int t = (9-t_it)%10;
while (true)
{
int it_cnt = Trie[now].next[t];
if (it_cnt == -1) t = (t+9)%10;
else if ((Trie[it_cnt].count == 1) and (same_flag) and (Trie[it_cnt].it == t_it)) t = (t+9)%10;
else
{
if (Trie[it_cnt].it != t_it) same_flag = false;
num = 10LL*num+static_cast<ll>((t+t_it)%10);
now = it_cnt;
break;
}
}
//std::printf("%d %d %d %lld %d %d %d %d\n",i,t_it,t,num,same_flag,Trie[now].count,Trie[now].it,t_it);
++i;
}
return num;
}
int main()
{
init();
reading();
for (int i=0;i<N;++i) add(i);
ll maximum = 0LL, minimum = 9223372036854775807LL, tmp;
for (int i=0;i<N;++i)
{
readin(i);
tmp = query_min();
if (tmp < minimum) minimum = tmp;
tmp = query_max();
if (tmp > maximum) maximum = tmp;
}
std::printf("%I64d %I64d",minimum,maximum);
}