1. 程式人生 > >poj—2528Mayor's posters-線段樹+區間離散化

poj—2528Mayor's posters-線段樹+區間離散化

題意:在牆上貼海報,海報可以互相覆蓋,問最後可以看見幾張海報

思路:線段樹+離散化

注意的是不能用普通的離散化,例如:

三張海報為:1~10 1~4 6~10

離散化時 X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 6, X[ 4 ] = 10
第一張海報時:牆的1~4被染為1;
第二張海報時:牆的1~2被染為2,3~4仍為1;
第三張海報時:牆的3~4被染為3,1~2仍為2。
最終,第一張海報就顯示被完全覆蓋了,於是輸出2,但實際上明顯不是這樣,正確輸出為3。

ps:

POJ構造的數軸是這樣的

|___|___|___|___|___|___|___|___|
  1   2   3   4   5   6   7   8
所以
輸入:1-10 1-4 5-10 得到的是2
輸入:1-10 1-4 6-10 得到的是3
為了解決這種缺陷,我們可以在排序後的陣列上加些處理,比如說 [1,2,6,10] 如果相鄰數字間距大於1的話,在其中加上任意一個數字,比如加成 [1,2,3,6,7,10],然後 再做線段樹就好了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int w=11111;
struct s{
    int i,j,k;
}a[15*w],b[w];
int x[w*3];
void build(int r,int i,int j)
{
    a[r].i=i;
    a[r].j=j;
    a[r].k=0;
    if(i==j)
    {
        return ;
    }
    int k=(i+j)/2;
    build(r<<1,i,k);
    build(r<<1|1,k+1,j);
}
int visit(int y,int j)
{
    int i=0,k;
    while(i<=j)
    {
        k=(i+j)/2;
        if(x[k]==y) return k;
        if(x[k]>y) j=k-1;
        else i=k+1;
    }
}
void pushdown(int r)
{
    if(a[r].k)
    {
        a[r<<1].k=a[r<<1|1].k=1;
    }
}
int query(int r,int i,int j)
{
    if(a[r].k) return 0;
    if(a[r].i>=i&&a[r].j<=j)
    {
        a[r].k=1;
        return 1;
    }
    pushdown(r);
    int y=0,k=(a[r].i+a[r].j)/2;
    if(j<=k) y=query(r<<1,i,j);
    else if(i>k) y=query(r<<1|1,i,j);
    else y=query(r<<1,i,j)|query(r<<1|1,i,j);  
    //返回1表示還有空隙
    if(a[r<<1].k&&a[r<<1|1].k)
        a[r].k=1;
    return y;
}
int main()
{
    int n,m,i,j,t,T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        t=0;
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&b[i].i,&b[i].j);
            x[t++]=b[i].i,x[t++]=b[i].j;
        }
        sort(x,x+t);
        j=0;
        for(i=1;i<t;i++)
        {
            if(x[i]!=x[j])
                x[++j]=x[i];//去重
        }
        for(i=j;i>0;i--)
        {
            if(x[i]-x[i-1]!=1) x[++j]=x[i-1]+1;
        }
        sort(x,x+j+1);
        build(1,0,j);
        t=0;
        for(i=n-1;i>=0;i--)
        {
            if(query(1,visit(b[i].i,j),visit(b[i].j,j)))
                t++;
        }
        printf("%d\n",t);
    }
return 0;
}