hdu5360优先队列

来源:互联网 发布:唐山炭知天下 编辑:程序博客网 时间:2024/05/22 11:04
priority_queue优先队列容器与队列一样,只能从队尾添加(插入)元素,从队头(队首)删除元素。但他有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按先进先出的原则进行,而是将当前队列中最大的元素出队。这点类似与给队列里的元素进行了由大到小的顺序排序。元素的比较规则默认为按元素的值的由大到小排序;当然,可以重载“<”操作符来重新定义比较规则;

使用priority_queue需要声明头文件#include <queue>;

优先队列的使用方法

优先队列包含入队push()(插入元素),出队pop()(删除元素),读取队头元素top(),判断队列是否为空empty()和读取队列元素数量size()等方法;
下例程序具体说明了优先队列的使用方法:
#include <iostream>
#include <queue>
using namespace std;


int main(int argc, char *argv[])
{
    //定义优先队列对象,元素类型为整型;
    priority_queue <int> pq;
    //入队,插入新的元素;
    pq.push(1);
    pq.push(2);
    pq.push(3);
    pq.push(9);
    //返回队列中元素的个数;
    cout << pq.size() << endl;
    while(!pq.empty()) {  // == pq.empty!=true;
        //读取当前队首元素;
        cout << pq.top() << " ";
        //出队,删除队首元素;
        pq.pop();
    }
    cout << endl;
    return 0;
}


运行结果为:
4
9 3 2 1

重载“<”操作符来定义优先级

如果优先队列的元素类型是结构体,可以通过在结构体中重载“<”操作符的方法来修改优先队列的优先性;
下例程序详细说明了在结构体中重载“<”操作符的方法;

运行结果为:
Bomi 18.5
Jack 68.5
Peti 90

#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;


struct Info
{
    string name;
    float score;
    //重载"<"操作符,指定优先级;
    bool operator < (const Info &a) const
    {
        //按score由小到大排列,如果要由大到小排列,使用“>”即可;
        return a.score < score;
    }
};

int main(int argc, char *argv[])
{
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
    //定义优先队列对象,元素类型为Info结构体型;
    priority_queue <Info> pq;
    Info info;  //定义结构体变量;

    //入队;
    info.name = "Jack";
    info.score = 68.5;
    pq.push(info);

    info.name = "Bomi";
    info.score = 18.5;
    pq.push(info);

    info.name = "Peti";
    info.score = 90;
    pq.push(info);
    //元素出队;
    while(!pq.empty()) {
        //返回队首元素;
        cout << pq.top().name << " " << pq.top().score << endl;
        //将队头元素弹出;
        pq.pop();
    }
    return 0;
}

重载“()”操作符来定义优先级

如果优先队列的元素不是结构体类型,则可以通过重载“()”操作符的方式来定义优先级,当然,元素是结构体类型,也可以通过重载“()”操作符的方法来定义优先级,而不是一定要在结构体内重载“<”操作符才行;

下例程序说明了重载“()”操作符的方法:

运行结果为:
1 5 9 28 34

#include <iostream>
#include <queue>
using namespace std;

//重载“()”操作符;
struct mycmp
{
    bool operator () (const int &a, const int &b)
    {
        //由小到大排列采用">"号,如果要由大到小排列,则采用"<"号;
        return a > b;
    }
};

int main(int argc, char *argv[])
{
    //定义优先队列,元素类型为Info的结构体,显式说明内部结构是vector;
    priority_queue <int, vector<int>, mycmp> pq;
    //入队;
    pq.push(1);
    pq.push(28);
    pq.push(9);
    pq.push(5);
    pq.push(34);
    //元素全部出队;
    while(!pq.empty()) {
        //返回队首元素;
        cout << pq.top() << " ";
        //删除队首元素;
        pq.pop();
    }
    cout << endl;
    return 0;
}

hdu5360的思路:

就是按l从小到大排列,一样大,再按r排序,用优先队列保证当前选择的是满足当前人数的最小的r(利用的贪心的策略),提前排序是保证可以开始并且一次性扫过去就能得到答案。

#include <iostream>#include <queue>#include <cstdio>#include<cstring>#include<stdlib.h>#include <algorithm>using namespace std;const int maxn=100010;typedef pair<int, int> PII;struct node{    int l,r,id;};bool cmp(node a,node b){    if(a.l==b.l)         return a.r<b.r;    return a.l<b.l;}node soda[maxn];int vis[maxn],b[maxn];int main(){    int T,n;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        memset(vis,0,sizeof(vis));        memset(b,0,sizeof(b));        for(int i=0; i<n; i++)        {            scanf("%d",&soda[i].l);            soda[i].id=i+1;        }        for(int i=0; i<n; i++)        {            scanf("%d",&soda[i].r);        }        int cnt=0,i=0;        priority_queue<PII>q;        sort(soda,soda+n,cmp);        while (1)        {            while (i < n && soda[i].l <= cnt) q.push(PII(-soda[i].r, soda[i].id)), ++i;            while (!q.empty() && -q.top().first < cnt) q.pop();            if (q.empty()) break;            b[cnt ++] = q.top().second;            q.pop();            vis[b[cnt - 1]] = 1;        }        printf("%d\n",cnt);        for(int i=1; i<=n; i++) if(!vis[i]) b[cnt++]=i;        printf("%d",b[0]);        for(int i=1; i<n; i++)        {            printf(" %d",b[i]);        }        printf("\n");    }    return 0;}

0 0
原创粉丝点击