CS Academy Dominant Free Sets

リンク : https://csacademy.com/contest/archive/task/dominant-free-sets/

問題概要

N個の頂点の座標が与えられる。任意の二頂点をP,Qとすると P_x>=Q_x と P_y>=Q_y を満たすものが存在しない、頂点の集合の選び方は何通りか10^{9}+7の余りを求めよ。

解説

dp[i] : i番目の頂点を集合に含むときの通り数 とすると、dp[i]=sum{j=0,1...n}{ if(!(i_x>=j_x&&i_y>=j_y)) dp[j]} となるだろう。しかし、これではdp[i]を求めることができない。なので、決める順番を決めることにする。今回はy座標でソートする。dp[i]をソート後のi番目の頂点を集合に含み、i番目までの頂点しか集合に含まないときの通り数とすると、dp[i]=sum{j=0,1...i-1}{if(j_x>i_x)dp[j]}+1(この「+1」はiの頂点のみの場合) と置くことができる。ここでsumの部分は区間の総和であるため、セグ木で高速化することができる。

LL n, ans,dp[110000];
Pll pos[110000];
Seg seg(110000);
int main() {
    cin >> n;
    rep(i, n) {
        cin >> pos[i].fir >> pos[i].sec;
    }
    sort(pos, pos + n, [](Pll x, Pll y) {return x.sec == y.sec ? x.fir < y.fir : x.sec < y.sec; });
    rep(i, n) {
        dp[i] = seg.getsum(pos[i].fir+1, 100001) + 1;
        seg.add(pos[i].fir, dp[i]);
    }
    rep(i, n) {
        ans += dp[i];
        ans %= MOD;
    }
    cout << ans<< endl; 
    return 0;
}