有n个左右端点都为整数的区间,判断每个区间是否有与其它某个区间相交(区间端点重合也算相交)。
第一个反应是线段树,先留一下,写个排序遍历的:
/*
struct Interval {
int start; //区间左端点
int end; //区间右端点
};
*/
struct IntervalWithPos
{
Interval in;
int pos;
IntervalWithPos(Interval i,int p):in(i),pos(p){}
bool operator<(const IntervalWithPos& oth)const
{
if ( in.start == oth.in.start )
return in.end<oth.in.end;
return in.start<oth.in.start;
}
};
// intervals包含n个区间
// 结果存放到isIntersected中(已分配空间,不需要push_back)
// isIntersected[i]表示第i个区间是否与其它区间相交
void intersected(vector<Interval> &intervals, vector<bool> &isIntersected) {
int n =intervals.size();
if ( n== 0 )
return;
typedef IntervalWithPos IPos;
vector<IPos> inters;
inters.reserve(n);
for(int i=0;i<n;i++)
inters.push_back(IPos(intervals[i],i));
sort(inters.begin(),inters.end());
int end=inters[0].in.end;
for(int i=1;i<n;i++)
{
if ( end >= inters[i].in.start)
isIntersected[inters[i].pos]=true;
end=max(end,inters[i].in.end);
}
int start=inters[n-1].in.start;
for(int i=n-2;i>=0;i--)
{
if ( start <=inters[i].in.end )
isIntersected[inters[i].pos]=true;
start=min(start,inters[i].in.start);
}
}
线段树确实还是不熟悉啊,昨天树里的每个节点保存什么,怎么更新想了半天,后来想到跟区间加和是一样的道理,每次加1而已。
const int MAXN= 10;
int cover[MAXN<<2];
int add[MAXN<<2];
void build(int rt)
{
memset(cover,0,sizeof(cover));
memset(add,0,sizeof(add));
}
void pushDown(int rt)
{
if ( add[rt]!= 0 )
{
add[rt<<1]+=cover[rt];
add[rt<<1|1]+=cover[rt];
cover[rt<<1]+=add[rt];
cover[rt<<1|1]+=add[rt];
add[rt]=0;
}
}
void pushUp(int rt)
{
cover[rt]=max(cover[rt<<1],cover[rt<<1|1]);
}
void insert(int rt,int l,int r,int L,int R)
{
if ( L<=l && r <=R )
{
add[rt]++;
cover[rt]++;
return;
}
pushDown(rt);
int mid=(l+r)>>1;
if ( L<=mid )
insert(rt<<1,l,mid,L,R);
if ( R>mid )
insert(rt<<1|1,mid+1,r,L,R);
pushUp(rt);
}
int query(int rt,int l,int r,int L,int R)
{
if (L<=l&&r<=R)
{
return cover[rt];
}
pushDown(rt);
int mid=(l+r)>>1;
int left=0,right=0;
if (L<=mid )
left=query(rt<<1,l,mid,L,R);
if ( R>mid )
right=query(rt<<1|1,mid+1,r,L,R);
pushUp(rt);
return max(left,right);
}
struct Interval {
int start; //区间左端点
int end; //区间右端点
};
// intervals包含n个区间
// 结果存放到isIntersected中(已分配空间,不需要push_back)
// isIntersected[i]表示第i个区间是否与其它区间相交
void intersected(vector<Interval> &intervals, vector<bool> &isIntersected) {
int n=intervals.size();
if (n<=1 )
return ;
build(1);
for(int i=0;i<n;i++)
insert(1,0,MAXN,intervals[i].start,intervals[i].end);
for(int i=0;i<n;i++)
{
int k = query(1,0,MAXN,intervals[i].start,intervals[i].end);
if ( k>1 )
isIntersected[i]=true;
}
}