题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6168
题意:有一个长度为n的序列a1……an,根据a序列生成了一个b序列,b[i] = a[i]+aj,然后有一个人把a,b序列按随机顺序混合了起来,现在问你初始的a序列是什么 ?
思路:用已确定的a[]数组来确定b[]数组的元素,从已知序列中删掉,再确定新的a[]数组元素,重复步骤。
模拟一下(假定输入数组为ss[]数组):
样例二: 1 2 3 3 4 4 5 5 5 6 6 6 7 7 7 8 8 9 9 10 11
首先,ss[]数组最小的两个数一定为a[]数组的前两个元素,我们以此为基础向后更新,因为直接排序会超时,这里我用是优先队列,即将ss[]数组入队num队列(队列sum是a[]数组和b[]数组的混合),
此时初始队列为:1 2 3 3 4 4 5 5 5 6 6 6 7 7 7 8 8 9 9 10 11;
先将a1和a2出队,而a1+a2=1+2=3;所以我们num队列中的一个3出队(由a1和a2组成的是b[]数组中的一个元素),num队列中剩下的3一定是a[]数组中的元素(此时我们确定a[]数组的元素组合只能组合出一个3),出队;
此时num队列变为4 4 5 5 5 6 6 6 7 7 7 8 8 9 9 10 11;
现在我们已知的a[]数组元素有1,2,3;他们能组成的b[]数组元素为4,5(这里只考虑包含新元素的情况);我们将确认的b[]数组元素放入另一个优先队列s;
队列s:4,5;(这里解释一下,队列s所存的元素就是b[]数组中的元素。我们用的是优先队列,每次最小的元素出队,用队列s去更新队列sum,找出a[]数组的元素。)
num队列中的4出队,此时队列中还有一个4,则4就是我们确定的a[]数组中的新元素(同理此时我们确定a[]数组的元素组合只能组合出一个4),现在我们已知的a[]数组元素有1,2,3,4;之后num队列中的5出队,此时队列s为空,以确认的新元素4更新队列s:5,6,7;重复以上步骤,最后得出所求数组a[]:1,2,3,4,5,6;
可能我写的有点混乱,但事实上代码是非常好理解的,调试一遍代码就清楚了(那我写这个有什么用?)。
Ps:感觉自己菜炸了 O_O !
#include<bits/stdc++.h>
using namespace std;
const int maxn= 125500;
priority_queue<int,vector<int>,greater<int> > num;
priority_queue<int,vector<int>,greater<int> > s;
int a[maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
int x;
for(int i=0; i<n; i++)
{
scanf("%d",&x);
num.push(x);
}
///前两个数
int tmp=0,tmp1;
a[tmp++]=num.top();
num.pop();
a[tmp++]=num.top();
num.pop();
s.push(a[0]+a[1]);//和
int l=0;
while(!num.empty())
{
int temp=num.top();
if(s.empty())
{
int w=num.top();
a[tmp++]=w;
for(int i=0; i<tmp-1; i++)
{
s.push(a[i]+w);
}
num.pop();
continue;
}
int temp1=s.top();
if(temp==temp1)
{
num.pop();
s.pop();
}
else
{
int w=num.top();
a[tmp++]=w;
for(int i=0; i<tmp-1; i++)
{
s.push(a[i]+w);
}
num.pop();
}
}
printf("%d\n",tmp);
for(int i=0; i<tmp; i++)
{
if(i!=0)
printf(" ");
printf("%d",a[i]);
}
printf("\n");
}
}