题目大意:有两个含有n个数的数组a,b,定义两个数列相似当且仅当a和b含有的元素完全相同,只有顺序可以不同,可以将某一个元素变为他的位数,例如123变成3,问最少需要多少次操作能使a和b相似
1<=n<=1e5;1<=ai,bi<1e9
思路:因为每个元素都小于1e9,所以每个数最多进行两次操作,我们事先记录每个数组中所有数字出现的次数,然后遍历,如果某个数在a和b中出现次数不同,就对他进行操作,维护答案和计数,接着数组中只剩下1-9的数可能数量不同,只需遍历2-9,找出数量不同的,变成1,维护答案和计数,因为所有数都能两两配对,所以剩下的1数量也一定相同
#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
const int N = 2e5 + 5;
int a[N], b[N];
int getdig(int x)
{//计算x是几位数
int ret = 0;
while (x)
{
x /= 10;
ret++;
}
return ret;
}
map<int,int> cnta, cntb;
int main()
{
int t;
cin >> t;
while (t--)
{
cnta.clear();
cntb.clear();
int n;
scanf("%d", &n);
int ans = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
cnta[a[i]]++;//记录每个数字的个数
}
for (int i = 1; i <= n; i++)
{
scanf("%d", &b[i]);
cntb[b[i]]++;
}
for (int i = 1; i <= n; i++)
{
if (a[i] > 9&&(cntb.find(a[i])==cntb.end()||cnta[a[i]]>cntb[a[i]]))
{//如果a中的某个数字在a,b出现次数不同
cnta[a[i]]--;
a[i] = getdig(a[i]);
cnta[a[i]]++;//把这个元素进行一次操作,维护计数
ans++;
}
if (b[i] > 9 && (cnta.find(b[i]) == cnta.end()||cntb[b[i]]>cnta[b[i]]))
{
cntb[b[i]]--;
b[i] = getdig(b[i]);
cntb[b[i]]++;
ans++;
}
}
for (int i = 2; i <= 9; i++)
{//进行过一轮操作后,剩下需要操作的只剩2-9
int temp = cnta[i] - cntb[i];
if (temp > 0)
{//某个数在a中比b多
cnta[i] = cntb[i];
cnta[1] += temp;//这个数变成1,维护计数
ans += temp;
}
else if (temp < 0)
{
cntb[i] = cnta[i];
cntb[1] -= temp;
ans -= temp;
}
}
printf("%d\n", ans);
}
}