有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; } }