POJ 2528 線段樹+座標離散化+雜湊+二分

來源:互聯網
上載者:User

題目大意:題目給定一面牆(一維),在牆上貼海報,(li-ri)的區間形式張貼n張海報,求最終在牆上能看見多少張海報?

區間覆蓋的線段樹的求法是這樣的,每個區間給定一個標記,例如(1,10),(2,6)張貼兩張海報,那麼(1,10)區間的節點就標記為1,(2,6)區間的節點就標記為2,這樣就實現了區間覆蓋,標記完之後會發現(1,1)為標記1,(2,6)為標記2,(7,10)為標記1,這樣會得出三段間斷的區間,怎樣來將這三段區間判斷為2個呢?用一個hash數組,對當前節點的標記進行1,0操作。因為每個結點都是記錄的自己所在區間的標號,所以即便是這個區間被其他區間劃分為K段,也可以通過對標記的1,0操作判斷之前是否被標記過,若沒有標記過沒那麼可見的海報數直接++就行了。否則不+;

題中的海報牆可是非常大的..10^7這樣對於空間開銷很大。這裡運用到了座標離散化的思想,將自己需要的座標保留,不需要的剔除掉,這裡可以參見LRJ黑書的切蛋糕離散化問題,但是黑書的特點就是含混不清,難以理解= =,所以看完之後我一直不知道怎麼來編碼實現這個問題。他給的例子也用很嚴重的二義性!關於離散化,網路上也沒有很好的解釋,因為離散化只是一種思想,對於具體題目會有不同的運用,舉個例子吧,例如給定區間為(1,10000),(200,1000),很明顯的,這兩段區間有利用價值的就是1,200,1000,10000這四個點,直接將他們排序,對於每個下標就是他們的映射,0,1,2,3,這樣比較好理解,所以在數組中儲存的就是array[0]=1,arry[1]=200;這樣有什麼用呢?我們使用線段樹進行操作的時候只是對這種數組下標進行操作,因為不管原來給定的座標值有多大,直接映射過來為較小的數,保證相對順序不變就可以了,也就是性質不變。原來的1->0,200>1,1000->3,我們若要執行其他的操作的話,就在這種下標去尋找原來的值就可以了。在這個題目中,只需要統計海報的總數,所以,長度便沒有那麼重要了。怎樣去利用下標來構造樹呢?之前我們儲存了座標的值,通過二分去尋找座標在數組中的位置,再將這些位置去構造二叉線段樹。

對於這個題目我不懂的就是為啥,兩個區間端點相差>1時,必須多插一個值?? 覺得沒有必要啊... 希望hh神犇能給我回複吧....

做完這道題,真的感覺線段樹有了那麼一點點的想法了,真的要活學活用啊~ 感謝hh神犇。

#include<iostream>#include<algorithm>#define MAXN 11111using namespace std;int X[MAXN*3],lx[MAXN],rx[MAXN];int col[MAXN<<4];bool hash[MAXN<<2];int cnt;void PushDown( int rt ){     if( col[rt]!=-1 )     {         col[rt<<1]=col[rt<<1|1]=col[rt];         col[rt]=-1;     }     return ;}int Bin( int key,int n ){    int left=0,right=n-1;    while( left<=right )    {           int m=(left+right)>>1;           if( X[m]==key )return m;           if( X[m]>key )right=m-1;           else left=m+1;    }    return -1;}void update( int l,int r,int c,int L,int R,int rt ){     if( l<=L&&R<=r ){         col[rt]=c;         return ;     }     PushDown(rt);     int m=(L+R)>>1;     if( l<=m ) update( l,r,c,L,m,rt<<1 );     if( r>m ) update( l,r,c,m+1,R,rt<<1|1 );}void query( int l,int r,int rt ){     if( col[rt]!=-1 )     {         if( !hash[col[rt]] ) cnt++;         hash[col[rt]]=true;         return ;     }     if( l==r )return ;     //PushDown(rt);     int m=( l+r )>>1;     query( l,m,rt<<1 );     query( m+1,r,rt<<1|1 );}int main(){    int T,n,nn,i;    scanf( "%d",&T );    while( T-- )    {           scanf( "%d",&n );           nn=0;           for( i=0;i<n;i++ )           {                scanf( "%d %d",&lx[i],&rx[i] );                X[nn++]=lx[i];                X[nn++]=rx[i];           }           sort( X,X+nn );           int m=1;           for( i=1;i<nn;i++ ){                if( X[i]!=X[i-1] )                     X[m++]=X[i];           }           for( i=m-1;i>=1;i-- ){                if( X[i]!=X[i-1]+1 )                    X[m++]=X[i]+1;           }           sort( X,X+m );           memset( col,-1,sizeof(col) );           for( i=0;i<n;i++ )           {                int l=Bin( lx[i],m );                int r=Bin( rx[i],m );                update( l,r,i,0,m,1 );           }           cnt=0;           memset( hash,false,sizeof(hash) );           query( 0,m,1 );           printf( "%d\n",cnt );     }    return 0;}




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.