Description
A rectangle is specified by a pair of coordinates (x1 , y1) and (x2 , y2) indicating its lower-left and upper-right corners (x1 <= x2 and y1 <= y2). For a pair of rectangles, A = ((X_A1, Y_A1), (X_A2, Y_A2)) and B = ((X_B1, Y_B1), (X_B2, Y_B2)), we define A <= B if X_A2<X_B1 and Y_A2<Y_B1. Given a number of rectangles on the plane, you are asked to find the length L of the longest sequence of rectangles (A1, A2, ..., AL) such that A1 <= A2 <= ... <= AL.
Input
The input contains multiple test cases. The first line of the input is an integer T, indicating the number of test cases. Each test case begins with a line containing a single integer n (1 <= n <= 100000), indicating the number of rectangles. Each of the next n lines contains four integers x1, y1, x2, y2 (- 1000000 <= x1 < x2 <= 1000000, -1000000 <= y1 < y2 <= 1000000), indicating the lower left and upper right corners of a rectangle.
Output
For each input test case, output a single integer indicating the length of the longest sequence.
Sample Input
2
3
1 5 2 8
3 -1 5 4
10 10 20 20
2
2 1 4 5
6 5 8 10
Sample Output
2
1
Source
6th BUPT Programming Contest Final
类似于最长上升子序列,不过数据量为10W,$O(n^{2})$的算法肯定是行不通的,而普通的最长上升序列二分法的$O(nlogn)$不能直接用于此,需要稍作修改,详见程序。(线段树的$O(nlogn)$也是可以的)
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <vector> #define MAXN 100010 struct rec { int x1,y1,x2,y2; bool operator < (const rec &x) const { return x2<x.x2; } } a[MAXN]; int T,n,i,j,tmp,ans,k,siz; int d[MAXN],g[MAXN]; std::vector<int> s[MAXN]; int bisearch1(int l,int r,int x) { if(x<=a[1].x2) return 0; if(a[r].x2<x) return r; int mid; while(l<r) { mid=(l+r)>>1; if(a[mid].x2<x) l=mid; else r=mid-1; if(l+1==r) { if(a[r].x2<x) return r; else return l; } } return l; } int bisearch2(int l,int r,int x) { if(x<=g[1]) return 0; if(g[r]<x) return r; int mid; while(l<r) { mid=(l+r)>>1; if(g[mid]<x) l=mid; else r=mid-1; if(l+1==r) { if(g[r]<x) return r; else return l; } } return l; } int main() { while(scanf("%d",&T)!=EOF) while(T--) { scanf("%d",&n); for(i=1;i<=n;++i) { scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2); s[i].clear(); d[i]=1; } std::sort(a+1,a+n+1); memset(g,127,sizeof(g)); for(i=2;i<=n;++i) { tmp=bisearch1(1,i-1,a[i].x1); if(tmp!=0) s[tmp].push_back(i); } for(i=1,ans=0;i<=n;++i) { if(a[i].y2<g[d[i]]) g[d[i]]=a[i].y2; siz=s[i].size(); for(j=0;j<siz;++j) { k=bisearch2(1,i,a[s[i][j]].y1); d[s[i][j]]=k+1; } if(d[i]>ans) ans=d[i]; } printf("%d\n",ans); } return 0; }