【BOI2011】trapezoid

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();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章