Description
考慮任意兩條選中的橫線。一個介於兩線之間的梯形Ti 有兩個頂點位於上面的直線,另外兩個頂點位於下面的直線。我們用ai, bi, ci 及di 分別代表梯形左上、右上、左下及右下的頂點。所有梯形的集合的一個子集S 被成爲獨立的,僅當任意兩個S 中的梯形不相交。
確定最大的梯形獨立子集的基數(最大集合意味着擁有最多元素的集合)。並且找到不同的最大獨立集的數量。找到的方案數模30013。
Input
輸入的第一行含一個整數N——梯形的數目。接下來N 行每行包含四個整數ai;,bi, ci 及di。沒有兩個梯形的頂點(角)重合。
Output
輸出的唯一一行應包含兩個用空格隔開的數字:第一個,最大獨立子集的基數;第二個,不同最大獨立子集數目模30013 後的值。
Sample Input
7
1 3 1 9
4 7 2 8
11 15 4 12
10 12 15 19
16 23 16 22
20 22 13 25
30 31 30 31
Sample Output
3 8
Data Constraint
• 1 <= N <= 100 000
• 1 <= ai, bi, ci, di <= 1 000 000 000
• 如果只有輸出的第一個數正確,那麼你可以得到測試點40% 的分數。
• 40% 的數據有N <= 5000
Solution
先按照下端點從小到大拍一波序。
再按照排好的順序來做,如果是左端點,那麼對應的是查詢操作,如果是右端點,那麼就對應一個插入操作。
查詢操作:查詢左端點的值-1所得到的答案+1表示從第一個矩形一直做到這一個矩形的答案。
插入操作:在右端點的值的位置插入查詢左端點得到的答案
這些可以用樹狀數組來維護
當然,這是要建立在先離散化的基礎之上的。(用STL離散化是真的省心)
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int p=30013;
const int maxn=100005;
struct kk{
int x,n;
inline void update(kk y){
if (y.x>x) x=y.x,n=y.n;
else if (y.x==x) n=(n+y.n)%p;
}
kk(){ x=n=0;}
} tr[maxn*2],f[maxn];
struct edge{
int x,y;
} a[2*maxn],b[2*maxn],c[2*maxn];
int n,i,j,tot,lim,x[2*maxn];
int read(){
int sum=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9') {
sum=sum*10+c-'0';
c=getchar();
}
return sum;
}
void add(int x,kk y){
while (x<=lim){
tr[x].update(y);
x+=(x&(-x));
}
}
kk query(int x){
kk w;
while (x){
w.update(tr[x]);
x-=(x&(-x));
}
return w;
}
bool cmp(int a,int b){return a<b;}
bool com(edge a,edge b){return a.x<b.x;}
void deal(){
tot=0;
int i;
fo(i,1,n) c[++tot].x=b[i].x,c[tot].y=i,c[++tot].x=b[i].y,c[tot].y=-i;
sort(c+1,c+tot+1,com);
fo(i,1,n) lim=max(lim,a[i].y);
fo(i,1,tot){
int x=c[i].y;
if (x<0) add(a[-x].y,f[-x]);
else {
kk t=query(a[x].x);
f[x].update(t);
f[x].x++;
if (f[x].x==1) f[x].n=1;
}
}
kk ans;
fo(i,1,n) ans.update(f[i]);
printf("%d %d\n",ans.x,ans.n);
}
int main(){
freopen("trapezoid.in","r",stdin);
freopen("trapezoid.out","w",stdout);
n=read();
fo(i,1,n) a[i].x=read(),a[i].y=read(),b[i].x=read(),b[i].y=read();
tot=0;
fo(i,1,n) x[++tot]=a[i].x,x[++tot]=a[i].y;
sort(x+1,x+tot+1,cmp);
tot=unique(x+1,x+tot+1)-x-1;
fo(i,1,n) a[i].x=lower_bound(x+1,x+tot+1,a[i].x)-x,a[i].y=lower_bound(x+1,x+tot+1,a[i].y)-x;
tot=0;;
fo(i,1,n) x[++tot]=b[i].x,x[++tot]=b[i].y;
sort(x+1,x+tot+1,cmp);
tot=unique(x+1,x+tot+1)-x-1;
fo(i,1,n) b[i].x=lower_bound(x+1,x+tot+1,b[i].x)-x,b[i].y=lower_bound(x+1,x+tot+1,b[i].y)-x;
deal();
}