有一兩年沒有搞了,有點生疏,這道題目是線段樹的,以前在學校搞過,
搞這道題目第二天才搞出來,而且參考了另外的解題報告。
問題的抽象如下,
// 給定一條數軸,長度為 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出現了...