有一两年没有搞了,有点生疏,这道题目是线段树的,以前在学校搞过,
搞这道题目第二天才搞出来,而且参考了另外的解题报告。
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;
}