Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 18816 Accepted Submission(s): 6416

Problem Description
还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小希只想让你把答案中最大的M个数告诉她就可以了。
给定一个包含N(N<=3000)个正整数的序列,每个数不超过5000,对它们两两相加得到的N*(N-1)/2个和,求出其中前M大的数(M<=1000)并按从大到小的顺序排列。

Input
输入可能包含多组数据,其中每组数据包括两行:
第一行两个数N和M,
第二行N个数,表示该序列。

Output
对于输入的每组数据,输出M个数,表示结果。输出应当按照从大到小的顺序排列。

Sample Input
4 4
1 2 3 4
4 5
5 3 6 4

Sample Output
7 6 5 5
11 10 9 9 8

在看堆排序 写了个裸的堆排序

TLE 代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[3005],b[3005*1508];
int n,m,t;
void down(int i) {
    int x,flag=0;
    while(i*2<=t&&flag==0) {
        if(b[i*2]>b[i])
            x=i*2;
        else x=i;
        if(i*2+1<=t) {
            if(b[x]<b[i*2+1])
                x=i*2+1;
        }
        if(x!=i) {
            swap(b[x],b[i]);
            i=x;
        }
        else flag=1;
    }

}
void creat() {
    for(int i=t/2;i>=1;i--)
        down(i);
}
void heapsort() {
    while(t>1) {
        swap(b[1],b[t]);
        t--;
        down(1);
    }
}
int main() {
    while(scanf("%d%d",&n,&m)!=EOF) {
        t=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n-1;i++)
            for(int j=i+1;j<=n;j++) {
                b[++t]=a[i]+a[j];
            }
        creat();
        heapsort();
        for(int i=1;i<=m;i++) {
            printf("%d",b[i]);
            if(i!=m) printf(" ");
        }
        printf("\n");
    }
    return 0;
}

然后看着 找找模板 优化 优化 优化….

AC代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[3005],b[3005*1508];
int n,m,t;
void up(int i) {
    int k=i/2;
    if(i==1) return;
    if(b[k]<b[i]) {
        swap(b[i],b[k]);
        up(k);
    }
    return;
}
void down(int i) {
    int x,flag=0;
    while(i*2<=t&&flag==0) {
        if(b[i*2]>b[i])
            x=i*2;
        else x=i;
        if(i*2+1<=t) {
            if(b[x]<b[i*2+1])
                x=i*2+1;
        }
        if(x!=i) {
            swap(b[x],b[i]);
            i=x;
        }
        else flag=1;
    }

}
int pop() {
    int x=b[1];
    swap(b[1],b[t--]);
    down(1);
    return x;
}
void ins(int i) {
    b[++t]=i;
    up(t);
}
int main() {
    while(scanf("%d%d",&n,&m)!=EOF) {
        t=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n-1;i++)
            for(int j=i+1;j<=n;j++) {
                ins(a[j]+a[i]);
            }
        for(int i=1;i<=m;i++) {
            printf("%d",pop());
            if(i!=m) printf(" ");
        }
        printf("\n");
    }
    return 0;
}