POJ2528 海報問題 線段樹 離散化

2021-06-19 10:13:40 字數 4107 閱讀 4340

有一兩年沒有搞了,有點生疏,這道題目是線段樹的,以前在學校搞過,

搞這道題目第二天才搞出來,而且參考了另外的解題報告。

問題的抽象如下,

// 給定一條數軸,長度為 l<=1千萬單位,然後在數軸上的某些區間染色,第i次對區間染色為i,共染色n<=10000次。給出每次染色的區間,問最後能看見多少種顏色。

// 線段樹處理染色問題,離散化處理,資料壓縮

// 建立線段樹和搜尋線段採用遞迴方式

// 利用完全二叉樹,n個點的層數為 logn + 1 

// 2w個點,層數為16,對應的樹節點個數為 2^16 = 64 * 1024 = 65536

// 用遞迴建立二叉樹要比用佇列快的多,

// 範圍 1, 20000 建立10次 createsegtree_re 執行速度是 15 ms

// 範圍 1, 20000 建立10次 createsegtree 執行速度是 782 ms

// 哈哈,poj過了,一步一步改為用遞迴方法,終於沒有超時,過了。。。。

// 2792k469ms c++ 5032b 2013-11-27 15:57:30

// 2792k485ms c++ 4401b 2013-11-27 16:02:47

// 2792k422ms c++ 4461b 2013-11-27 16:06:30

整個**如下:(採用遞迴方式)

#include#include#include#include #include #include #include using namespace std;

#include #include //#include "mysys.h"

//#include struct segtreenode;};

segtreenode g_segtree[100000] = {};

bool g_segflag[10001] = {};

int createsegtree_re(int icen, int ileft, int iright) // 遞迴建立完全二叉樹

int imid = (ileft + iright) / 2;

createsegtree_re(icen*2, ileft, imid);

createsegtree_re(icen*2 + 1, imid+1, iright);

return 0;

}void throughsegtree_re(int iinleft, int iinright, int iinfo, int icen)

if(iinleft <= g_segtree[icen].ileft && iinright >= g_segtree[icen].iright)

if(0 != g_segtree[icen].iinfo) // 當前節點有顏色,傳遞給孩子

throughsegtree_re(iinleft, iinright, iinfo, icen * 2);

throughsegtree_re(iinleft, iinright, iinfo, icen * 2 + 1);

return ;

}int g_inum = 0;

void dfsinfo(int icen)

return ; }

if(g_segtree[icen].ileft != g_segtree[icen].iright) }

void clear()

int main()

if(maptemp.end() == maptemp.find(iright))

vctpair.push_back(make_pair(ileft, iright));

} int itempindex = 1;

for(it = maptemp.begin(); it != maptemp.end(); it++)

for(itvct = vctpair.begin(); itvct != vctpair.end(); itvct++)

itreeleft = 1;

itreeright = itempindex-1;

//createsegtree(itreeleft, itreeright);

clear();

createsegtree_re(1, itreeleft, itreeright);

int iflag = 1;

for(itvct = vctpair.begin(); itvct != vctpair.end(); itvct++)

dfsinfo(1);

printf("%d\n", g_inum); }

return 0;

}

整個**如下:(採用棧和佇列方式,總是超時)

#include#include#include#include #include #include #include using namespace std;

#include //#include "mysys.h"

//#include struct segtreenode;};

struct qdata;};

segtreenode g_segtree[200000] = {};

int createsegtree(int ileft, int iright) // 利用佇列廣度搜尋建立完全二叉樹

imid = (adata.ir + adata.il) / 2;

que.push(qdata(adata.i*2, adata.il, imid));

que.push(qdata(adata.i*2 + 1, imid+1, adata.ir));

} return 0;

}int throughsegtree(int iinleft, int iinright, int iinfo)

stackstnode;

if(iinleft >= g_segtree[1].ileft && iinright <= g_segtree[1].iright)

int itop = 0;

int imid = 0;

int itleft = 0;

int itright = 0;

while(!stnode.empty()) // 深度優先搜尋

if(itleft == g_segtree[itop].ileft && itright == g_segtree[itop].iright)

imid = (g_segtree[itop].ileft + g_segtree[itop].iright) / 2;

if(itright <= imid)

}else if(itleft > imid)

}else

}g_segtree[itop].iinfo = 0; // 自己顏色清空

} return 0;

}int main()

if(maptemp.end() == maptemp.find(iright))

vctpair.push_back(make_pair(ileft, iright));

} int itempindex = 1;

for(it = maptemp.begin(); it != maptemp.end(); it++)

for(itvct = vctpair.begin(); itvct != vctpair.end(); itvct++)

itreeleft = 1;

itreeright = itempindex+1;

createsegtree(itreeleft, itreeright);

int iflag = 1;

for(itvct = vctpair.begin(); itvct != vctpair.end(); itvct++)

queueque;

int ifront = 0;

if(0 == g_segtree[1].iinfo)

else

while(!que.empty()) // 廣度優先搜尋

}else

}printf("%d\n", settemp.size()); }

return 0;

}

POJ2528 離散化線段樹

將資料離散化在使用線段樹 有一面牆,被等分為1qw份,乙份的寬度為乙個單位寬度。現在往牆上貼n張海報,每張海報的寬度是任意的,但是必定是單位寬度的整數倍,且 1qw。後貼的海報若與先貼的海報有交集,後貼的海報必定會全部或區域性覆蓋先貼的海報。現在給出每張海報所貼的位置 左端位置和右端位置 問張貼完n...

poj 2528 線段樹 離散化

題目連線 題目大意 在一面牆上貼海報,牆很長,後面貼上去的海報要覆蓋掉之前貼上去的海報,現在向牆上逐一的貼海報,問到最後牆上可以看見的海報有幾種?方法 線段樹,離散化 include include include include using namespace std define maxn 10...

poj2528(離散化 線段樹)

題意 在1 10 7的長度上貼海報,求能看到的海報數目 解題思路 10 7無論用樸素法或線段樹解都會超時超記憶體,所以要進行離散化。所謂離散化就是把有限的個體對映到有限的空間,以此提高演算法的時空效率以這題的測試資料為例,本題的五個區間為1 4,2 6,8 10,3 4,7 10 其中10和4出現了...