1055 The World's Richest (25 分)

题意

给出\(N\)个人的姓名、年龄及其拥有的财富值,然后进行K次查询。每次查询要求输出年龄范围在[AgeL, AgeR]的财富值从大到小的前M人的信息。如果财富值相同,则年龄小的优先;如果年龄也相同,则姓名的字典序小的优先。

暴力代码,水了\(22pts\)

const int N=1e5+10;
struct Node
{
    string name;
    int age;
    int worth;
    bool operator<(const Node &W) const
    {
        if(worth != W.worth) return worth > W.worth;
        if(age != W.age) return age < W.age;
        return name < W.name;
    }
}a[N];
int n,m;

int main()
{
    cin>>n>>m;

    for(int i=0;i<n;i++)
        cin>>a[i].name>>a[i].age>>a[i].worth;

    int kase=1;
    while(m--)
    {
        int k,l,r;
        cin>>k>>l>>r;

        vector<Node> v;
        for(int i=0;i<n;i++)
            if(a[i].age >= l && a[i].age <= r)
                v.pb(a[i]);

        cout<<"Case #"<<kase++<<':'<<endl;

        if(v.size() == 0) cout<<"None"<<endl;
        else
        {
            sort(v.begin(),v.end());
            for(int i=0;i<k && i<v.size();i++)
                cout<<v[i].name<<' '<<v[i].age<<' '<<v[i].worth<<endl;
        }
    }
    //system("pause");
    return 0;
}

一巧妙的做法,时间复杂度:\(O(nm)\),量级在\(10^7\),可以过。

const int N=1e5+10;
struct Node
{
    string name;
    int age;
    int worth;
    bool operator<(const Node &W) const
    {
        if(worth != W.worth) return worth > W.worth;
        if(age != W.age) return age < W.age;
        return name < W.name;
    }
}a[N];
int n,m;

int main()
{
    cin>>n>>m;

    for(int i=0;i<n;i++)
    {
        a[i].name.resize(8);
        scanf("%s %d %d",&a[i].name[0],&a[i].age,&a[i].worth);
    }
    sort(a,a+n);

    int kase=1;
    while(m--)
    {
        int k,l,r;
        cin>>k>>l>>r;

        printf("Case #%d:\n",kase++);

        int cnt=0;
        for(int i=0;cnt<k && i<n;i++)
            if(a[i].age >= l && a[i].age <= r)
            {
                printf("%s %d %d\n",a[i].name.c_str(),a[i].age,a[i].worth);
                cnt++;
            }

        if(cnt == 0) puts("None");
    }
    //system("pause");
    return 0;
}

晴神的做法:
注意到\(M\)的范围仅在100以内,因此可以进行预处理,即将每个年龄中财富在前100名以内的人全都存到另一个数组中(因为某个年龄中财富值在100名以外的人永远不会被输出),后面查询的操作均在这个新数组中进行。这个预处理操作将显著降低查询的复杂度,时间复杂度:\(O(200*100*m)\),量级在\(2 \times 10^6\)

const int N=1e5+10;
struct Node
{
    string name;
    int age;
    int worth;
    bool operator<(const Node &W) const
    {
        if(worth != W.worth) return worth > W.worth;
        if(age != W.age) return age < W.age;
        return name < W.name;
    }
}a[N],b[N];
int book[210];
int tot;
int n,m;

int main()
{
    cin>>n>>m;

    for(int i=0;i<n;i++)
    {
        a[i].name.resize(8);
        scanf("%s %d %d",&a[i].name[0],&a[i].age,&a[i].worth);
    }

    sort(a,a+n);

    for(int i=0;i<n;i++)
        if(book[a[i].age] < 100)
        {
            b[tot++]=a[i];
            book[a[i].age]++;
        }

    int kase=1;
    while(m--)
    {
        int k,l,r;
        cin>>k>>l>>r;

        printf("Case #%d:\n",kase++);

        int cnt=0;
        for(int i=0;i<tot;i++)
            if(b[i].age >= l && b[i].age <= r)
            {
                printf("%s %d %d\n",b[i].name.c_str(),b[i].age,b[i].worth);
                cnt++;
                if(cnt == k) break;
            }

        if(cnt == 0) puts("None");
    }
    //system("pause");
    return 0;
}

posted @ 2021-02-15 11:10  Dazzling!  阅读(27)  评论(0编辑  收藏  举报