HDU 6168 Numbers

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=6168

题目大意:将a[i] + a[j]  n >= j > i >= 1的结果放在b数组中。现在将a,b的数据混在一块,请将原始的a数据顺序输出,题目保证有且仅有一组解,并且a数组是非递减的。

解题思路:首先可以发现,混合数组c中c[0] c[1] 一定是在a中的,然后我们将c排序,考虑一个c[x] ,如果c[x] = a[i] + a[j],a[i] a[j]现在都已经确定在a中,并且这样的c[x]第一次出现,那么这个c一定是a中两个数相加而来的,如果这个c找不到对应的a[i] a[j],那么他就是a中的元素。那么我们就可以用一个访问标记来判断是否a[i] + a[j]已经被使用过。但是这样子复杂度会达到0(mn^2).  事实上,对c排序后,对于一个c[x]来说,我们只需看a[i] + a[j]的最小值是否和c[x]相等即可。所以我们可以用一个优先队列来维护已知的a中的数据所能够形成得和。

注意0个数据和1个数据时候的输出。。。

代码:

const int maxn = 2e5 + 5;
ll a[maxn];
int tot = 0, m;
ll b[505]; 
struct node{
    ll v;
    int i, j;
    bool operator < (const node &t) const{
        if(v != t.v) return v > t.v;
        else{
            if(i != t.i) return i > t.i;
            else return j > t.j;
        }
    }
};
priority_queue<node> q;

void solve(){
    if(m == 0){
        printf("0\n\n");
        return;
    }
    if(m == 1){
        printf("1\n%d\n", a[0]);
        return;
    }
    sort(a, a + m);
    b[0] = a[0]; b[1] = a[1];
    tot = 2;
    node u; u.v = a[0] + a[1]; u.i = 0; u.j = 1;
    q.push(u);
    for(int i = 2; i < m; i++){
        ll x = a[i];
        bool flag = false;
        if(q.empty()) {
            b[tot] = x;
            int len = tot;
            for(int j = 0; j < len; j++) {
                node tmp; tmp.v = x + b[j]; tmp.i = j; tmp.j = tot;
                q.push(tmp);
            }
            tot++;
            continue;
        }
        node u = q.top();
        if(u.v != x) {
            b[tot] = x;
            int len = tot;
            for(int j = 0; j < len; j++) {
                node tmp; tmp.v = x + b[j]; tmp.i = j; tmp.j = tot;
                q.push(tmp);
            }
            tot++;
        }
        else q.pop();
    }
    sort(b, b + tot);
    printf("%d\n", tot);
    for(int i = 0; i < tot; i++){
        printf("%lld", b[i]);
        if(i < tot - 1) printf(" ");
        else puts("");
    }
}
int main(){
    while(scanf("%d", &m) != EOF){
        for(int i = 0; i < m; i++) scanf("%lld", &a[i]);
        solve();
    }
}

题目:

Numbers

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 289    Accepted Submission(s): 148


Problem Description
zk has n numbers a1,a2,...,an . For each (i,j) satisfying 1≤i<j≤n, zk generates a new number (ai+aj) . These new numbers could make up a new sequence b1b2,...,bn(n1)/2 .
LsF wants to make some trouble. While zk is sleeping, Lsf mixed up sequence a and b with random order so that zk can't figure out which numbers were in a or b. "I'm angry!", says zk.
Can you help zk find out which n numbers were originally in a?
 

 

Input
Multiple test cases(not exceed 10).
For each test case:
The first line is an integer m(0≤m≤125250), indicating the total length of a and b. It's guaranteed m can be formed as n(n+1)/2.
The second line contains m numbers, indicating the mixed sequence of a and b.
Each ai is in [1,10^9]
 

 

Output
For each test case, output two lines.
The first line is an integer n, indicating the length of sequence a;
The second line should contain n space-seprated integers a1,a2,...,an(a1a2...an) . These are numbers in sequence a.
It's guaranteed that there is only one solution for each case.
 

 

Sample Input
6 2 2 2 4 4 4 21 1 2 3 3 4 4 5 5 5 6 6 6 7 7 7 8 8 9 9 10 11
 

 

Sample Output
3 2 2 2 6 1 2 3 4 5 6
 

 

Source
posted @ 2017-08-22 20:52  EricJeffrey  阅读(123)  评论(0编辑  收藏  举报