poj 2528 (線段樹+離散化)
阿新 • • 發佈:2019-02-18
大致題意: 有一面牆,被等分為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; }