POJ2528 海报问题(线段树+离散化)

来源:互联网 发布:那个软件看寅唱会 编辑:程序博客网 时间:2024/05/17 07:40

有一两年没有搞了,有点生疏,这道题目是线段树的,以前在学校搞过,

搞这道题目第二天才搞出来,而且参考了另外的解题报告。

http://blog.csdn.net/lyy289065406/article/details/6799170

问题的抽象如下,

// 给定一条数轴,长度为 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过了,一步一步改为用递归方法,终于没有超时,过了。。。。
// 2792K 469MS C++ 5032B 2013-11-27 15:57:30
// 2792K 485MS C++ 4401B 2013-11-27 16:02:47
// 2792K 422MS C++ 4461B 2013-11-27 16:06:30


整个代码如下:(采用递归方式)

#include<iostream>#include<vector>#include<map>#include <string>#include <set>#include <stack>#include <queue>using namespace std;#include <stdio.h>#include <string.h>//#include "mysys.h"//#include <Windows.h>struct segTreeNode{int iID;int iLeft;int iRight;int iInfo;segTreeNode():iID(-1){iInfo = 0;iLeft = -1;iRight = -1;};};segTreeNode g_SegTree[100000] = {};bool g_SegFlag[10001] = {};int createSegTree_re(int iCen, int iLeft, int iRight) // 递归创建完全二叉树{g_SegTree[iCen].iID = iCen;g_SegTree[iCen].iLeft = iLeft;g_SegTree[iCen].iRight = iRight;g_SegTree[iCen].iInfo = 0;if(iLeft == iRight){return 1;}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(iInRight < g_SegTree[iCen].iLeft || iInLeft > g_SegTree[iCen].iRight) // 没有交集{return ;}if(iInLeft <= g_SegTree[iCen].iLeft && iInRight >= g_SegTree[iCen].iRight){g_SegTree[iCen].iInfo = iInfo;return ;}if(0 != g_SegTree[iCen].iInfo) // 当前节点有颜色,传递给孩子{g_SegTree[iCen * 2 + 1].iInfo = g_SegTree[iCen].iInfo; // 颜色传给右孩子g_SegTree[iCen * 2].iInfo = g_SegTree[iCen].iInfo; // 颜色传给左孩子g_SegTree[iCen].iInfo = 0; // 自己颜色清空}throughSegTree_re(iInLeft, iInRight, iInfo, iCen * 2);throughSegTree_re(iInLeft, iInRight, iInfo, iCen * 2 + 1);return ;}int g_iNum = 0;void dfsInfo(int iCen){if(0 != g_SegTree[iCen].iInfo){if(!g_SegFlag[g_SegTree[iCen].iInfo]){g_SegFlag[g_SegTree[iCen].iInfo] = true;g_iNum++;}return ;}if(g_SegTree[iCen].iLeft != g_SegTree[iCen].iRight){dfsInfo(iCen*2);dfsInfo(iCen*2 + 1);}}void clear(){memset(g_SegFlag,0,sizeof(g_SegFlag) / sizeof(g_SegFlag[0]));  g_iNum = 0;}int main(){int iNumTest = 0;int iNumSeg = 0;int iLeft = 0;int iRight = 0;int iTreeLeft = 0;int iTreeRight = 0;map<int, int>  mapTemp;map<int, int>::iterator it;vector<pair<int, int> >  vctPair;vector<pair<int, int> >::iterator itvct;scanf("%d",&iNumTest);for(int i = 0; i < iNumTest; i++){mapTemp.clear();vctPair.clear();scanf("%d",&iNumSeg);for(int j = 0; j < iNumSeg; j++){scanf("%d %d", &iLeft, &iRight);if(mapTemp.end() == mapTemp.find(iLeft)){mapTemp.insert(make_pair(iLeft, 0));}if(mapTemp.end() == mapTemp.find(iRight)){mapTemp.insert(make_pair(iRight, 0));}vctPair.push_back(make_pair(iLeft, iRight));}int iTempIndex = 1;for(it = mapTemp.begin(); it != mapTemp.end(); it++){it->second = iTempIndex;iTempIndex = iTempIndex + 1;}for(itvct = vctPair.begin(); itvct != vctPair.end(); itvct++){itvct->first = mapTemp[itvct->first];itvct->second = mapTemp[itvct->second];}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++){//throughSegTree(itvct->first, itvct->second, iFlag++);throughSegTree_re(itvct->first, itvct->second, iFlag++, 1);}dfsInfo(1);printf("%d\n", g_iNum);}return 0;}


整个代码如下:(采用栈和队列方式,总是超时)

#include<iostream>#include<vector>#include<map>#include <string>#include <set>#include <stack>#include <queue>using namespace std;#include <stdio.h>//#include "mysys.h"//#include <Windows.h>struct segTreeNode{int iID;int iLeft;int iRight;int iInfo;segTreeNode():iID(-1){iInfo = 0;iLeft = -1;iRight = -1;};};struct qdata{int i;int iL;int iR;qdata(int _in_i = -1, int _in_iL = -1, int _in_iR = -1):i(_in_i), iL(_in_iL), iR(_in_iR){};};segTreeNode g_SegTree[200000] = {};int createSegTree(int iLeft, int iRight) // 利用队列广度搜索创建完全二叉树{int iMid = 0;qdata aData;queue<qdata> que;que.push(qdata(1, iLeft, iRight));while(!que.empty()){aData = que.front();que.pop();g_SegTree[aData.i].iID = aData.i;g_SegTree[aData.i].iLeft = aData.iL;g_SegTree[aData.i].iRight = aData.iR;g_SegTree[aData.i].iInfo = 0;if(aData.iL == aData.iR){continue;}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){if(iInLeft > iInRight){return 1;}stack<int>  stNode;if(iInLeft >= g_SegTree[1].iLeft && iInRight <= g_SegTree[1].iRight){stNode.push(1);}int iTop = 0;int iMid = 0;int iTLeft = 0;int iTRight = 0;while(!stNode.empty()) // 深度优先搜索{iTop = stNode.top();stNode.pop();//cout<<iInLeft<<" "<<iInRight<<" "<<iTop<<" "<<stNode.size()<<endl;iTLeft = iInLeft;if(iInLeft < g_SegTree[iTop].iLeft){iTLeft = g_SegTree[iTop].iLeft;}iTRight = iInRight;if(iInRight > g_SegTree[iTop].iRight){iTRight = g_SegTree[iTop].iRight;}if(iTLeft == g_SegTree[iTop].iLeft && iTRight == g_SegTree[iTop].iRight){g_SegTree[iTop].iInfo = iInfo;continue;}iMid = (g_SegTree[iTop].iLeft + g_SegTree[iTop].iRight) / 2;if(iTRight <= iMid){stNode.push(iTop * 2);if(0 != g_SegTree[iTop].iInfo) // 要有颜色才能往下传{g_SegTree[iTop * 2 + 1].iInfo = g_SegTree[iTop].iInfo; // 颜色传给右孩子}}else if(iTLeft > iMid){stNode.push(iTop * 2 + 1);if(0 != g_SegTree[iTop].iInfo){g_SegTree[iTop * 2].iInfo = g_SegTree[iTop].iInfo; // 颜色传给左孩子}}else{stNode.push(iTop * 2 + 1);stNode.push(iTop * 2);if(0 != g_SegTree[iTop].iInfo){g_SegTree[iTop * 2 + 1].iInfo = g_SegTree[iTop].iInfo; // 颜色传给右孩子g_SegTree[iTop * 2].iInfo = g_SegTree[iTop].iInfo; // 颜色传给左孩子}}g_SegTree[iTop].iInfo = 0; // 自己颜色清空}return 0;}int main(){int iNumTest = 0;int iNumSeg = 0;int iLeft = 0;int iRight = 0;int iTreeLeft = 0;int iTreeRight = 0;map<int, int>  mapTemp;map<int, int>::iterator it;set<int> setTemp;vector<pair<int, int> >  vctPair;vector<pair<int, int> >::iterator itvct;scanf("%d",&iNumTest);for(int i = 0; i < iNumTest; i++){mapTemp.clear();vctPair.clear();setTemp.clear();scanf("%d",&iNumSeg);for(int j = 0; j < iNumSeg; j++){scanf("%d %d", &iLeft, &iRight);if(mapTemp.end() == mapTemp.find(iLeft)){mapTemp.insert(make_pair(iLeft, 0));}if(mapTemp.end() == mapTemp.find(iRight)){mapTemp.insert(make_pair(iRight, 0));}vctPair.push_back(make_pair(iLeft, iRight));}int iTempIndex = 1;for(it = mapTemp.begin(); it != mapTemp.end(); it++){it->second = iTempIndex;iTempIndex = iTempIndex + 1;}for(itvct = vctPair.begin(); itvct != vctPair.end(); itvct++){itvct->first = mapTemp[itvct->first];itvct->second = mapTemp[itvct->second];}iTreeLeft = 1;iTreeRight = iTempIndex+1;createSegTree(iTreeLeft, iTreeRight);int iFlag = 1;for(itvct = vctPair.begin(); itvct != vctPair.end(); itvct++){throughSegTree(itvct->first, itvct->second, iFlag++);}queue<int>  que;int iFront = 0;if(0 == g_SegTree[1].iInfo){que.push(1);}else{setTemp.insert(1);}while(!que.empty())  // 广度优先搜索{iFront = que.front();que.pop();if(0 == g_SegTree[iFront].iInfo){if(g_SegTree[iFront].iLeft != g_SegTree[iFront].iRight){que.push(iFront * 2);que.push(iFront * 2 + 1);}}else{setTemp.insert(g_SegTree[iFront].iInfo);}}printf("%d\n", setTemp.size());}return 0;}




原创粉丝点击