ZOJ 3612 && HDU 4864 (multiset 的应用)

本文详细介绍了两个算法题的解决方法:一是如何在进行add和remove操作后,通过multiset数据结构跟踪并找出中位数;二是探讨了在给定机器和任务条件下,通过贪心算法实现资源最优分配,以完成最多任务并获取最多收益的问题。文章提供了具体的代码实现,适合对数据结构与算法感兴趣的读者深入学习。

ZOJ 3612

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4736

题意:在进行add和remove等操作下,找出这些数中的中位数

思路:利用multiset可以对用指针对中位数进行跟踪,如果共有偶数个数,让指针指向相对较小的那个数

 

 

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <set>
#include <iterator>
#include <functional>

using namespace std;

typedef long long int ll;

multiset <ll> ms;
multiset <ll> :: iterator it, tt;
multiset <ll> :: iterator p;

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        ms.clear();
        int n;
        char s[20];
        int a;
        scanf("%d", &n);
        while(n--)
        {
            scanf("%s%d", s, &a);
            if(!strcmp(s, "add"))
            {
                ms.insert(a);
                if(ms.size() == 1)
                    it = ms.begin();
                else
                {
                    if(ms.size() % 2 && a >= *it)
                        it++;
                    if(ms.size() % 2 == 0 && a < *it)
                        it--;
                }
            }
            else
            {
                p = ms.find(a);
                if(p == ms.end())
                {
                    printf("Wrong!\n");
                    continue;
                }
                else
                {
                    if(*it == a)
                    {
                        p = it;
                        if(ms.size() % 2 == 0)
                            it++;
                        else
                            it--;
                    }
                    else
                    {
                        if(ms.size() % 2 && a > *it)
                            it--;
                        if(ms.size() % 2 == 0 && a < *it)
                            it++;
                    }
                    ms.erase(p);
                }
            }
            if(ms.empty())
                printf("Empty!\n");
            else
            {
                if(ms.size() % 2)
                    printf("%lld\n", *it);
                else
                {
                    tt = it;
                    tt++;
                    ll ans = *it + *tt;
                    if(ans % 2 == 0)
                        printf("%lld\n", ans / 2);
                    else
                        printf("%.1lf\n", 1.0 * ans / 2);
                }
            }
        }
    }
    return 0;
}

 

 

 

 

HDU 4864(多校第一场)

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

题意:在一定量的机器和任务中找出 最好的策略使得能在完成最多任务的基础上获得最多的钱,一个机器想完成某任务,必须工作时间>=该任务时间,且等级>=该任务等级,一台机器一天只能工作一次

思路:贪心,在先将机器和任务都按等级进行排序,然后对于每台机器找出符合上述两条件的最合适的任务(对于每项任务,由于钱与机器无关,所以每项任务要派低级的机器去完成),注意upper_bound()和lower_bound()的应用

 

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>

using namespace std;

const int MAX = 1e5 + 10;
typedef long long ll;

struct node
{
    ll x, y;
    bool operator < (const node &a ) const
    {
        return x  < a.x || (x == a.x && y < a.y);
    }
};

struct node1
{
    ll x, y;
    bool operator < (const node1 &a ) const
    {
        return y < a.y || (y == a.y && x < a.x);
    }
};

int N, M;
node1 mac[MAX], task[MAX];

void solve()
{
    int j = 1;
    int cnt = 0;
    ll ans = 0;
    multiset <node> s;
    for (int i = 1; i <= N; ++i)
    {
        while (j <= M && task[j].y <= mac[i].y )
        {
            s.insert((node)
            {
                task[j].x, task[j++].y
            });
        }
        multiset <node>::iterator it = s.upper_bound( (node)
        {
            mac[i].x, mac[i].y
        });
        if (it != s.begin())
        {
            --it;
            ans += 500 * (it -> x) + 2 * (it -> y);
            ++cnt;
            s.erase(it);
        }
    }
    printf("%d %I64d\n", cnt, ans);
}

int main()
{
    while (scanf("%d%d", &N, &M) != EOF)
    {
        for (int i = 1; i <= N; ++i) scanf("%I64d%I64d", &mac[i].x, &mac[i].y);
        for (int i = 1; i <= M; ++i) scanf("%I64d%I64d", &task[i].x, &task[i].y);
        sort(mac + 1, mac + 1 + N);
        sort(task + 1, task + 1 + M);
        solve();
    }
    return 0;
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值