Numbers
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 603 Accepted Submission(s): 318
Problem Description
zk has n numbers a1,a2,…,an. For each (i,j) satisfying 1≤i
题意:
给定初始的n个数字和n个数字的二元和,求原始的n个数字
将b数组排序,取出最小的两项作为
a1,a2
a1,a2
,删除
a1,a2,a1+a2
,再取出最小项作为
a3
,再删除
a3,a1+a3,a2+a3
,再取出最小项作为
a4
,依次列推。
用set或者map/离散后的桶排来快速维护这个过程
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <map>
using namespace std;
typedef long long LL;
const int maxn=125260;
int a[maxn],b[maxn];
int n,cnt,l;
map<int,int>Q;
inline int IN()
{
int x=0,y=1;char c;
for(c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')y=-1;
for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
return x*y;
}
int main()
{
while(~scanf("%d",&n))
{
Q.clear();
for(int i=0;i<n;++i)
{
a[i]=IN();
Q[a[i]]++;
}
sort(a,a+n);
n=unique(a,a+n)-a;
b[0]=a[0];
Q[a[0]]--;
if(Q[a[0]])
{
b[1]=a[0];
Q[a[0]]--;
l=0;
}
else
{
b[1]=a[1];
Q[a[1]]--;
l=1;
}
int x=lower_bound(a,a+n,b[0]+b[1])-a;
Q[a[x]]--;
cnt=1;
for(int i=l;i<n;++i)
{
while(Q[a[i]])
{
b[++cnt]=a[i];
Q[a[i]]--;
for(int j=0;j<cnt;++j)
{
x=lower_bound(a,a+n,b[j]+a[i])-a;
Q[a[x]]--;
}
}
}
printf("%d\n%d",cnt+1,b[0]);
for(int i=1;i<=cnt;++i)printf(" %d",b[i]);
printf("\n");
}
return 0;
}