1. 程式人生 > >POJ 2528 線段樹離散化

POJ 2528 線段樹離散化

[解題報告】
題目大意:
給定長度區間(L,R)//L,R<=1e7,
給出N個區間操作,把li-ri區間貼上海報 //N《=1e5
求:有多少張海報沒有被完全覆蓋

這道題目的關鍵在於,直接開1e7的線段樹一定會MLE,但我們觀察到一共只有不超過1e5張海報,如果每張海報我們只取它的兩個端點,只對它的端點進行處理,空間複雜度就會大大降低。
所以如何處理呢?
比如區間[1,4],[5,6]有四個不同端點,說明我們需要把他對映到線段樹上四個不同的位置。
我們從1開始對線段樹的葉子節點進行標記,那麼對映到的相對應的線段樹區間為:
[1,4]->[1,2]
[5,6]->[3,4]
這時候出現一個問題:
我們先後貼上[1,10],[1,4],[5,10],對映為:[1,4],[1,2],[3,4]只能看見兩張海報
如果先後貼上[1,10],[1,4],[7,10],對映為:[1,4],[1,2],[3,4],只能看見兩張海報。
哪裡出了問題?
問題在於:
如果兩條相鄰線段並不相交,離散化之後,它變成了相交!
所以維護這樣的性質:如果兩個頂點並不緊鄰,那麼我們離散化之後,它們仍然不能緊鄰。方法是在兩個頂點之間再插入一個頂點。

到了這裡,大部分問題就解決了。
還需要思考一個問題:如何查詢沒有被完全覆蓋的海報的數目。
容易想到,我們更新的時候,給區間(l,r)打上標記i表示當前位置的海報是i,這樣最後統計有多少個不同的i即可。
為了不重複查詢相同的,沒有被完全覆蓋的i,如: (1,10),( 3,4 ),(7,8)更新之後的標記就是1,2,1,3,1,會出現多個第1張海報的標記,我們需要單獨設定一個hash陣列,如果某張海報已經被統計過了,就不再重複統計。

這樣,剩下的就是線段樹模板的內容了。
剩下的細節可以參考程式碼。我的線段樹風格參考劉汝佳的《訓練指南》。

【參考程式碼】

#include<iostream>
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1e5+50; int N,m,cnt; int l[maxn],r[maxn],vis[maxn],X[maxn]; int cover[maxn*4]; void uniq( int nn ) { m=0; X[++m]=X[1]; for( int i=2; i<=nn; i++ ) { if( X[i]!=X[i-1
] )X[++m]=X[i]; } sort( X+1,X+1+m ); int t=m; for( int i=1;i<t;i++ ) { if( X[i]!=X[i+1]-1 )X[++m]=X[i]+1; } sort( X+1,X+1+m ); } void build( int O, int L, int R ) { if(L==R)cover[O]=-1; else { int mid=(L+R)/2; build(O*2+1,mid+1,R ); build( O*2,L,mid ); cover[O]=-1; } } void pushdown( int O ) { if( cover[O]!=-1 ) { cover[O*2]=cover[O*2+1]=cover[O]; cover[O]=-1; } } void update( int O, int L, int R, int qL, int qR, int c ) { if( qL<=L && R<=qR ) { cover[O]=c; } else { pushdown( O ); int mid=(L+R)/2; if( qL<=mid )update( O*2,L,mid, qL,qR,c ); if( qR>mid )update( O*2+1, mid+1,R,qL,qR,c ); } } void query( int O, int L, int R ) { if( L==R ) { if( cover[O]!=-1 && !vis[cover[O]] ) { vis[cover[O]]=1; cnt++; } } else { pushdown(O); int mid=(L+R)/2; query( O*2, L,mid ); query( O*2+1,mid+1,R ); } } int main() { //freopen("2528","r",stdin); int T; cin>>T; while(T--) { scanf( "%d",&N ); int nn=0; for( int i=1; i<=N; i++ ) { scanf( "%d%d",&l[i],&r[i] ); X[++nn]=l[i]; X[++nn]=r[i]; } sort( X+1,X+1+nn ); uniq(nn); build( 1,1,m ); for( int i=1; i<=N; i++ ) { int left=lower_bound( X+1,X+1+m,l[i] )-X; int right=lower_bound( X+1,X+1+m,r[i] )-X; update( 1,1,m,left,right,i ); } memset( vis,0,sizeof vis ); cnt=0; query( 1,1,m ); printf( "%d\n",cnt ); } return 0; }

相關推薦

POJ 2528 線段 離散 逆向思維

要求:向長度為1e8的牆上貼最多1e4個長度不等的海報,每個海報貼在牆上任意位置,問最後能見到幾個海報(見到海報的一部分也算是見到該海報)。 方法:線段樹區間修改 離散化 逆向思維 1.建造一個1e8的線段樹必定TLE,因此需要離散化(壓縮區間)。 此題離散化具體步驟:先用ql陣列和qr

poj 2528 線段+離散

E - 成段更新 Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Description The

POJ 2528 線段離散

[解題報告】 題目大意: 給定長度區間(L,R)//L,R<=1e7, 給出N個區間操作,把li-ri區間貼上海報 //N《=1e5 求:有多少張海報沒有被完全覆蓋 這道題目的關鍵在於,直接開1e7的線段樹一定會MLE,但我們觀察到一共只有不

POJ 2528 線段+離散

//線段樹的建樹過程主要有兩種形式,一種形式是 // [1,3] // [1,2] [2,3] //另外一種形式是 // [1,3] // [1,2] [3,3] // [1

POJ 2528 (線段 + 離散)

Mayor's posters Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been

poj 2528(線段+離散)

如圖,貼海報,後面的海報可以貼在前面的海報的上面,按給定的順序在區間為(l,r)的位置去貼海報,問最後可以在表面看見的海報有多少張 給定的區間範圍很大,為1 <= li <= ri <= 10000000 靜態的話,直接用線段樹進行區間更新,需要10

poj 2528 (線段+離散)

大致題意:     有一面牆,被等分為1QW份,一份的寬度為一個單位寬度。現在往牆上貼N張海報,每張海報的寬度是任意的,但是必定是單位寬度的整數倍,且<=1QW。後貼的海報若與先貼的海報有交集,後貼的海報必定會全部或區域性覆蓋先貼的海報。現在給出每張海報

POJ 3277 線段+離散

題意: 給定n個線段以及沒個線段上的高度,求最終所有線段的矩形面積並。 分析: 由於資料範圍較大,所以採用離散化,再用每個點進行建樹,之前沒這麼建過線段樹,學到了。 #include<cstdio> #include<algorithm> #i

2528 線段 + 離散

#include<iostream> #include<cstdio> #include<algorithm> #include<set> using namespace std; const int maxn = 1e5;

POJ 2528 Mayor's posters (線段 離散+區間更新+區間求值 )

href eof 求值 給定 一個點 一個 stream 問題 void 題目鏈接:http://poj.org/problem?id=2528 題意:塗色問題,給定n個要塗色的區間(每次用的顏色不一樣,顏色覆蓋性極強),問最後能看到多少種顏色。(貼海報問題轉換) 題解

poj 2528 線段+特殊離散

cto 1-1 there sync ali after hat tor memory Mayor‘s posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions:

poj 2528 Mayor's posters(線段+離散)

The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at

POJ 2528 Mayor's posters(線段+離散

Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 60691 Accepted: 17565 Description The citizens of Byteto

線段 + 離散 + 詳細註釋】北大 poj 2528 Mayor's posters

/* THE PROGRAM IS MADE BY PYY */ /*----------------------------------------------------------------------------// Copyright (c) 2011 panyanyany All rig

POJ 2528 Mayor's posters (線段+離散 成段替換)

題目大意: 就是在一段區間上貼海報, 後來的區間會把前面來的區間覆蓋掉, 為貼完海報後能看到幾張海報(只看到一部分也算看到) 大致思路: 就是區間替換更新, 標記一下當前區間的所有的海報是否一致, 用懶惰標記標記一下當前區間的類別 聽說資料比較水...布吉島嚴格的資料下這

POJ 2528 經典!線段離散

http://poj.org/problem?id=2528 題意:n(n<=10000)個人依次貼海報,給出每張海報所貼的範圍li,ri(1<=li<=ri<=10000000)。求出最後還能看見多少張海報。 解法:離散化,如下面的例子(題

線段+離散操作(poj 2528)

#include<iostream> #include<cstdio> #include<algorithm> #define Pn 10005 #define MAXN 1000005 using namespace std; int tN,pN; struct Tnod

POJ 2482】 Stars in Your Window(線段+離散+掃描線)

d+ opera algorithm ans som lov ble word wait 【POJ 2482】 Stars in Your Window(線段樹+離散化+掃描線) Time Limit: 1000MS M

POJ 1151 Atlantis 線段+離散

roc 線段樹 aps sin program cal ase gree org 題目鏈接:http://poj.org/problem?id=1151 http://acm.hdu.edu.cn/showproblem.php?pid=1542 題目大意:給你幾個矩形的

N - Picture POJ - 1177(矩形周長並 + 線段 + 離散

本程式碼採用的是橫向掃描一遍和縱向掃描一遍來得到最終的結果,核心部分就是求舉行周長並,當然也要對線段樹比較熟悉才行,畢竟矩形周長並,面積並,面積交都要用到線段樹來計算。說說求舉行周長並的過程吧,我們先計算橫向線段的長度,把所有座標的y軸座標按照升序排列,掃描線從y的最小值依次向上掃描,求出每