/***********************************************************************************************
题目描述:请编写程序,找出下面 “ 输入数据及格式 ” 中所描述的输入数据文件中最大重叠区间的大小。
对一个正整数 n ,如果 n 在数据文件中某行的两个正整数(假设为 A 和 B )之间,即 A<=n<=B 或 A>=n>=B ,则 n 属于该行;如果 n 同时属于行 i 和 j ,则 i 和 j 有重叠区间;重叠区间的大小是同时属于行 i 和 j 的整数个数。
例如,行( 10 20 )和( 12 25 )的重叠区间为 [12 20] ,其大小为 9 ;行( 20 10 )和( 12 18 )的重叠区间为 [10 12] ,其大小为 3 ;行 (20 10) 和( 20 30 )的重叠区间大小为 1 。
输入数据:程序读入已被命名为 input.txt 的输入数据文本文件,该文件的行数在 1 到 1,000,000 之间,每行有用一个空格分隔的 2 个正整数,这 2 个正整数的大小次序随机,每个数都在 1 和 2^32-1 之间。(为便于调试,您可下载测试 input.txt 文件,实际运行时我们会使用不同内容的输入文件。)
输出数据:在标准输出上打印出输入数据文件中最大重叠区间的大小,如果所有行都没有重叠区间,则输出 0 。
评分标准:程序输出结果必须正确,内存使用必须不超过 256MB ,程序的执行时间越快越好。
*/
/***********************************************************************************************
思路描述:动态规划,数组leftarr[i][j]描述的是,左端点小于等于leftarr[i][0]的所有线段中,
右端点的最大值为leftarr[i][1]。对于线段(left,right),二分法找i,使得leftarr[i][0]是比left小的最大数,
计算最大线段值,修改leftarr[i][1];如果需要,删除leftarr[j](j>i)后面的线段。
算法的时间复杂度也是O(NlogN),N为线段个数。但由于删除冗余的线段,总体时间比普通的排序再比较的算法要快,
测试发现快40%(见结果比较)。空间复杂度为线段个数。
**************************************************************************************/
/***********************************************************************************************
源代码,包括三部分:自己算法代码,他人算法的源代码,比较两者效率的源代码 (c++, 通过eclipse+CDT+MinGW编译):
#include <stdio.h>
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <fstream>
#include <stdlib.h>
#include "time.h"
using namespace std;
#define max(x, y)((x)<(y))? (y): (x)
#define min(x, y)((x)<(y))? (x): (y)
class BStarMaxInterSeg
{
//(left,所有左端点比left小的线段中,最大的的右端点值)
map<unsigned int, unsigned int> leftarr;
unsigned maxseg;
public:
int addseg(unsigned int segleft, unsigned int segright);
unsigned int getmaxseg();
BStarMaxInterSeg();
int clear();
};
BStarMaxInterSeg::BStarMaxInterSeg(){maxseg=0;}
int BStarMaxInterSeg::clear(){maxseg=0;leftarr.clear();return 1;}
unsigned int BStarMaxInterSeg::getmaxseg(){return maxseg;}
int BStarMaxInterSeg::addseg(unsigned int segleft, unsigned int segright){
map<unsigned int, unsigned int>::iterator cur;
map<unsigned int, unsigned int>::iterator last;//在cur之后,右端点比cur大的第一个节点
unsigned int go;
if(((segright-segleft)+1)<=maxseg) return 1;
go=0;
cur=leftarr.find(segleft);
if(cur!=leftarr.end()){
if (cur->second > segright)
maxseg=max(maxseg, (segright-segleft)+1);
else {
maxseg=max(maxseg, (cur->second-segleft)+1);
cur->second=segright;
go=1;
}
}
else{
maxseg=max(maxseg, (segright-segleft)+1);
leftarr.insert(pair<unsigned int, unsigned int>(segleft,segright));
cur=leftarr.find(segleft);
if(cur!=leftarr.begin()) {
cur--;
if(cur->second > segright) {
maxseg=max(maxseg, (segright-segleft)+1);
cur++;
leftarr.erase(cur);
}
else {
if(cur->second>segleft)
maxseg=max(maxseg, (cur->second-segleft)+1);
cur++;
go=1;
}
}
else go=1;
}
if(go==1){
last=cur;
last++;
while(last!=leftarr.end()){
if(last->second < cur->second)
maxseg=max(maxseg, (last->second - last->first)+1);
else {
if(cur->second>last->first)
maxseg=max(maxseg, (cur->second - last->first)+1);
break;
}
last++;
}
if(last==leftarr.end()) last--;
if(last!=cur) last--;
if(last!=cur){
cur++;
leftarr.erase(cur,last);
}
}
return 1;
}
/*********************************************test****************************************************/
//来源http://www.cnblogs.com/kaikai/archive/2005/09/21/241452.html
int cmp(const void *a, const void *b)
{
return *(unsigned int*)a > *(unsigned int*)b;
}
inline unsigned int cover(unsigned int n[2], unsigned int e)
{
unsigned int left = n[0];
unsigned int right = min(n[1], e);
if (left <= right)
return right - left + 1;
return 0;
}
class BStarMaxInterSeg_test{
unsigned int map[1000000][2];
unsigned num;
public:
unsigned int add(unsigned int x, unsigned int y);
unsigned int getmax();
BStarMaxInterSeg_test();
};
BStarMaxInterSeg_test::BStarMaxInterSeg_test(){num=0;}
unsigned int BStarMaxInterSeg_test::add(unsigned int x, unsigned int y){
map[num][0] = x;
map[num][1] = y;
num++;
return num;
}
unsigned int BStarMaxInterSeg_test::getmax(){
unsigned int i = 0;
unsigned int end;
unsigned int maxcover = 0, c;
qsort(map, num, sizeof(int)*2, cmp);
end = map[0][1];
for (i = 1; i < num; i++)
{
c = cover(map[i], end);
if (c > maxcover)
maxcover = c;
if (map[i][1] > end)
{
end = map[i][1];
}
}
return maxcover;
}
/*************************************compare*********************************************************/
int doit(){
unsigned const int maxnum=1000000;
unsigned int num, x,y,t,i,tt;
BStarMaxInterSeg* a;
BStarMaxInterSeg_test* b;
srand(time(0));
clock_t start,finish;
double totaltime;
for(tt=0;tt<10;tt++){
start=clock();
for(i=1;i<10;i++){
a=new BStarMaxInterSeg();
for(num=0;num<maxnum;num++){
x=(unsigned int)(rand());
y=(unsigned int)(rand());
if(x>y) {t=x;x=y;y=t;}
a->addseg(x,y);
}
a->getmaxseg();
delete a;
}
finish=clock();
totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
cout<<"my time:"<<totaltime<<endl;
start=clock();
for(i=1;i<10;i++){
b=new BStarMaxInterSeg_test();
for(num=0;num<maxnum;num++){
x=(unsigned int)(rand());
y=(unsigned int)(rand());
if(x>y) {t=x;x=y;y=t;}
b->add(x,y);
}
b->getmax();
delete b;
}
finish=clock();
totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
cout<<"test time:"<<totaltime<<endl;
cout<<endl;
}
return 1;
}
**************************************************************************************/
/***********************************************************************************************
两种算法效率比较:
my time:0.61
test time:0.984
my time:0.593
test time:1.016
my time:0.625
test time:0.969
my time:0.625
test time:0.922
my time:0.61
test time:0.969
my time:0.609
test time:0.891
my time:0.625
test time:0.968
my time:0.609
test time:0.954
my time:0.625
test time:0.937
my time:0.609
test time:0.938
**************************************************************************************/