POJ 2528 Mayor‘s poster 線段樹+離散化


給一塊最大為10^8單位寬的牆面,貼poster,每個poster都會給出數據 a,b,表示該poster將從第a單位占據到b單位,新貼的poster會覆蓋舊的,最多有10^4張poster,求最后貼完,會看到幾張poster (哪怕只露出一個單位,也算該poster可見);

我一看這么大數據,又看了下時間限制只有1s,不科學啊,如果真的按10^8建樹不可能過時間啊,而且根據它的空間限制,大概只能建10^7這么大的數組。

后來搜博客發現大家的標題都寫着離散化,原來用離散化做這個題目,但是我不會離散化,我想找一篇純講離散化的博文來好好研究下,。。。沒找到,所以原諒我,這個題目是仔仔細細的分析了別人的原題代碼才寫出來的,否則我真的不知道怎么弄離散化。

所謂離散化,把a,b所有出現的數字全部排序一遍,新的值就是他們的下標,當然重復的不算,然后每個a,b就會賦予一個更小的值,但完全不影響其功能,由於每個不同值都考慮進去了,所以區間縮小之后,不會出現覆蓋混亂,最多是正好全部覆蓋。。。。

然后說起這個線段樹要維護的,其實就是一個量,該區間是否被覆蓋,采取從后往前貼poster,這個跟之前做個一個排隊插隊的題目同理,從后往前,則狀態一定固定了,所以更加方便了,只要判斷在已經覆蓋了這么多poster的情況下,是否還有空余區間就行了。

 

話說期間WA了幾次不明不白是因為,我忘了用懶惰標記和懶惰更新了,果然好久沒寫線段樹了。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 25010
#define Lson x<<1,l,mid
#define Rson (x<<1|1),mid+1,r

using namespace std;

struct node {
    int val;
    int num;
} pos[N];
bool flag;
bool d[N*3];
int p[N*3];
bool cmp2(node a,node b)
{
    if (a.val<b.val) return true;
    return false;
}
bool cmp(node a,node b)
{
    if (a.num>b.num) return true;
    if (a.num==b.num && a.val<b.val) return true;
    return false;
}
void getup(int x)
{
    if (d[x<<1]==true || d[x<<1|1]==true)
     d[x]=true;
    else
    d[x]=false;
}
void build(int x,int l,int r)
{
    d[x]=true;
    p[x]=0;
    if (l==r){
        return;
    }
    int mid=(l+r)>>1;
    build(Lson);
    build(Rson);
    getup(x);
}
void pushdown(int x,int l,int r)
{
    if (!p[x] || l>=r) return;
    d[x<<1]=d[x<<1|1]=false;
    p[x<<1]=p[x<<1|1]=p[x];
    p[x]=0;
}
void query(int L,int R,int x,int l,int r)
{
    if (L<=l && r<=R)
    {
        if (d[x])
        {
         flag=true;
         d[x]=false;
         p[x]=1;
        }
        return;
    }
    if (p[x])
       pushdown(x,l,r);
    int mid=(l+r)>>1;
    if (L>mid && d[x<<1|1]) query(L,R,Rson);
    else
    if (R<=mid && d[x<<1]) query(L,R,Lson);
    else
    if (L<=mid && R>mid){
      if (d[x<<1]) query(L,R,Lson);
      if (d[x<<1|1]) query(L,R,Rson);
    }
    getup(x);
}
int main()
{
    int t;
    scanf("%d",&t);
    while (t--)
    {
        int n;
        int i,j,k;
        scanf("%d",&n);
        int a,b;
        for (i=0;i<n;i++)
        {
            scanf("%d%d",&pos[i<<1].val,&pos[i<<1|1].val);
            pos[i<<1].num=pos[i<<1|1].num=i;
        }
        sort(pos,pos+2*n,cmp2);
        int cur=0,pre=-1;
        for (j=0;j<2*n;j++)
        {
            if (pre!=pos[j].val){
               pre=pos[j].val;
               pos[j].val=++cur;
            }
            else{
                pos[j].val=cur;
            }
            //cout<<pre<<" "<<pos[j].val<<endl;
        }

        build(1,1,cur);

        sort(pos,pos+2*n,cmp);
        int ans=0;
        for (i=0;i<n;i++)
        {
            //cout<<pos[i<<1].val<<" "<<pos[i<<1|1].val<<endl;
            flag=false;
            query(pos[i<<1].val,pos[i<<1|1].val,1,1,cur);
            if (flag) {ans++;}
        }
        printf("%d\n",ans);
    }
    return 0;
}

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com