poj2528 Mayor's posters,优先队列

来源:互联网 发布:企业管理优化方案 编辑:程序博客网 时间:2024/06/06 19:19
poj2528 Mayor's posters,优先队列

给你一些海报,贴在墙上的顺序,问最后可见的有几张。墙可以看成一个线段,没有高度。

这种问题当然线段树可以解决。区间更新。最后扫一遍有几种。
但是这种离线的区间问题,用左进右出的做法更简单。

这里用到一个堆/优先队列。连离散化都不用,排个序即可。
每条线段化为两个点,左端点和右端点+1。排序一下这些点。
还是从左往右扫,每次先把该位置起始的线段号加入堆,结束的线段删除(用一个数组out标记即可)。
然后查看堆中最大的是哪个线段,则该位置就是被这个线段覆盖。

开个vis数组统计一下哪些线段可见即可。

STL简直赞。

poj终于水了300道,可以向某人交差了。。。

///--------------------------------------------

把do while的缩进改了,不要再看错了额。。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;#define NN 20100#define inf 101000000pair<int,int> v[NN];int p;int out[NN],vis[NN];int work(){    memset(out,0,sizeof(out));    memset(vis,0,sizeof(vis));    priority_queue<int> q;    int ret=0;    int i,u;    for(i=0;i+1<=p;){        do{            ++i;            if (v[i].second>0){                q.push(v[i].second);            }            else {                out[-v[i].second]=1;            }        }while(v[i].first==v[i+1].first);        while(!q.empty()){            u=q.top();            if (!out[u]) break;            else q.pop();        }        if (q.empty()) continue;        if (vis[u]==0) {ret++;vis[u]=1;}    }    return ret;}int main(){    int cas,s,b,i,ans,n;    scanf("%d",&cas);    while(cas--){        scanf("%d",&n);        p=0;        v[0]=make_pair(0,0);        for(i=1;i<=n;++i){            scanf("%d%d",&s,&b);            v[++p]=make_pair(s,i);            v[++p]=make_pair(b+1,-i);        }        v[p+1]=make_pair(inf,n+1);        sort(v+1,v+p+1);        ans=work();        printf("%d\n",ans);    }    return 0;}



0 0
原创粉丝点击