1. 程式人生 > >poj 2528 (線段樹+離散化)

poj 2528 (線段樹+離散化)

大致題意:     
      有一面牆,被等分為1QW份,一份的寬度為一個單位寬度。現在往牆上貼N張海報,每張海報的寬度是任意的,但是必定是單位寬度的整數倍,且<=1QW。後貼的海報若與先貼的海報有交集,後貼的海報必定會全部或區域性覆蓋先貼的海報。現在給出每張海報所貼的位置(左端位置和右端位置),問張貼完N張海報後,還能看見多少張海報        
   線段樹就不說了》》主要是離散化怎麼處理。。。

轉:        離散化就是壓縮區間,使原有的長區間對映到新的短區間,但是區間壓縮前後的覆蓋關係不變。舉個例子:有一條1到10的數軸(長度為9),給定4個區間[2,4] [3,6] [8,10] [6,9],覆蓋關係就是後者覆蓋前者,每個區間染色依次為 1 2 3 4。現在我們抽取這4個區間的8個端點,2 4 3 6 8 10 6 9然後刪除相同的端點,這裡相同的端點為6,則剩下2 4 3 6 8 10 9對其升序排序,得2 3 4 6 8 9 10然後建立對映2     3     4     6     8     9   10↓     ↓      ↓     ↓     ↓     ↓     ↓1     2     3     4     5     6     7那麼新的4個區間為 [1,3] [2,4] [5,7] [4,6],覆蓋關係沒有被改變。新數軸為1到7,即原數軸的長度從9壓縮到6,顯然構造[1,7]的線段樹比構造[1,10]的線段樹更省空間,搜尋也更快,但是求解的結果卻是一致的。 離散化時有一點必須要注意的,就是必須先剔除相同端點後再排序,這樣可以減少參與排序元素的個數,節省時間。
 


User: 1013101127
Memory: 2180K Time: 610MS
Language: G++ Result: Accepted
Source Code
#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int cas;
int n;


int logo[100008][3];
struct poit
{
    int pp;
    int num;
}mem[100400*3];


int f[100008];
int ans=0;


bool cmp(poit a,poit b)
{
    return a.num<b.num;
}


struct node
{
    int color;
    int l;
    int r;
}p[100009];


void built(int t,int lc,int rc)//建樹
{
    p[t].l=lc;
    p[t].r=rc;
    p[t].color=0;
    if(lc==rc)return ;
    built(2*t,lc,(lc+rc)/2);
    built(2*t+1,(lc+rc)/2+1,rc);
}


void change(int t,int lc,int rc,int col)//更新各點
{
    if(p[t].l==lc&&p[t].r==rc)
    {
        p[t].color=col;
        return ;
    }
    if(p[t].color>0&&p[t].color!=col)
    {
        p[2*t].color=p[2*t+1].color=p[t].color;
        p[t].color=0;
    }
    int mid=(p[t].l+p[t].r)/2;
    if(rc<=mid)
    change(2*t,lc,rc,col);
    else if(lc>mid)
    change(2*t+1,lc,rc,col);
    else
    {
        change(2*t,lc,mid,col);
        change(2*t+1,mid+1,rc,col);
    }
}


void query(int t)//查詢
{
    if(p[t].color!=0)
    {
        if(!f[p[t].color])
        {
            f[p[t].color]=1;
            ans++;
        }
        return ;
    }
    query(2*t);
    query(2*t+1);
}




int main()
{
    cin>>cas;
    while(cas--)
    {
        cin>>n;
        for(int i=0;i<n;i++)
        {
            cin>>logo[i][0]>>logo[i][1];
            mem[i*2].pp=-(i+1);
            mem[i*2].num=logo[i][0];
            mem[i*2+1].pp=(i+1);
            mem[i*2+1].num=logo[i][1];
        }


        sort(mem,mem+2*n,cmp);


        int tmp=mem[0].num;
        int sum=1;
        for(int i=0;i<2*n;i++)
        {
            if(mem[i].num!=tmp)
            {
                sum++;
                tmp=mem[i].num;
            }
            if(mem[i].pp<0)
            {
                logo[-mem[i].pp-1][0]=sum;
            }
            else
            {
                logo[mem[i].pp-1][1]=sum;
            }
        }
        built(1,1,sum);
        for(int i=0;i<n;i++)
        {
           change(1,logo[i][0],logo[i][1],i+1);
        }
        memset(f,0,sizeof(f));
        ans=0;
        query(1);
        cout<<ans<<endl;
    }
    return 0;
}