POJ 2528 Mayor's posters (线段树+离散化)

来源:互联网 发布:hbuilder for mac下载 编辑:程序博客网 时间:2024/04/27 09:17

http://poj.org/problem?id=2528


这题一定要写个题解。Orz。
不信看图,五月多做过一次,一直RE。现如今来做,仍然RE多发。


这里写图片描述


题意:在墙壁上贴广告,广告的版面有大有小,并且贴广告有先后之分,后面贴的广告会覆盖前面的广告,求解最后能看到的广告面。

本题数据太大,要用到离散化,意思是将区间范围很大的数据集映射到较小的数据集。
离散化的步骤:

  • 读取一对区间(x,y),用一个结构体(这里用arr)来存储这些点:arr[i].st =x,arr[i].ed=y;同时用另外一个离散的数组has来存储这些点,has[t++]=x,has[t++]=y;
  • 把has数组sort一遍
  • 把has数组unique(去重)一遍
    int tt=unique(has,has+t)-has;
  • 接下来更新线段树的时候,每个值通过二分得到:
    int xx= lower_bound(has,has+tt,arr[i].st)
    int yy= lower_bound(has,has+tt,arr[i].ed)
    update(xx,yy);

  • 然后就没有然后了 ==


只不过这题的不同的是,题目给的数字代表的是一个单位长度,而不是具体的一个点,普通的离散化会造成错误。所以在区间长度大于1的时候,往往在区间多加一个点。我省掉了这个步骤,我是在不管是否大于1,区间都在左右端点分别再加点。
这题让我RE的不是数组开大开小的问题,是一个query懒人操作没有处理好的问题。
错错更健康,以后不再错就好 ==


#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define mset(x,y)  memset(x,y,sizeof(x))#define lson l,mid,i<<1#define rson mid+1,r,i<<1|1using namespace std;const int N = 10000 +10;int ans;struct Node{    int st,ed;}arr[N];//记录区间的起点和终点bool vis[N];int has[N*4],tr[N*16];//注意数组范围,一定要开这么大void built(int l,int r,int i){    tr[i]=0;    if(l==r)  return;    int mid=(l+r)>>1;    built(lson);    built(rson);    return;}void pushdown(int i){    tr[i<<1] = tr[i<<1|1] = tr[i];    tr[i] = 0;    return;}void update(int l,int r,int i,int a,int b,int x){    if(l>=a&&r<=b)    {        tr[i] = x;        return;    }    if(tr[i]) pushdown(i);    int mid=(l+r)>>1;    if(mid>=a)  update(lson,a,b,x);    if(mid<b) update(rson,a,b,x);    return;}void query(int l,int r,int i,int a,int b){    if(l>=a && r<=b &&tr[i]!=0)    {               if(vis[tr[i]]) ans++,vis[tr[i]]=false;        return;    }    if(l==r) return;//RE多发的关键处,Orz!!!    if(tr[i]) pushdown(i);    int mid= (l+r)>>1;    if(mid>=a) query(lson,a,b);    if(mid<b) query(rson,a,b);    return;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n;        scanf("%d",&n);        mset(has,0);        int t=0;        for(int i=0;i<n;i++)        {            scanf("%d%d",&arr[i].st,&arr[i].ed);            has[t++]=arr[i].st;            has[t++]=arr[i].st+1;//奇妙的地方            has[t++]=arr[i].ed;            has[t++]=arr[i].ed-1;//奇妙的地方        }        sort(has,has+t);        int tt=unique(has,has+t)-has;        built(1,tt,1);        mset(vis,true);        ans=0;        for(int i=0;i<n;i++)        {            int x = lower_bound(has,has+tt,arr[i].st) - has + 1;//数组是从0开始的,所以+1保证正数性            int y = lower_bound(has,has+tt,arr[i].ed) - has + 1;            update(1,tt,1,x,y,i+1);        }       query(1,tt,1,1,tt);       printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击