Submission #1197926

#TimeUsernameProblemLanguageResultExecution timeMemory
1197926polarity사다리꼴 (balkan11_trapezoid)C++20
100 / 100
214 ms27164 KiB
/**
 * Solution by Charles Ran (polarity.sh)
 * Date: 2025-05-07
 * Contest: Balkan OI 2011
 * Problem: trapezoids
**/

#include <bits/stdc++.h>
using namespace std;

using ull = unsigned long long;
using ll = long long;
using vi = vector<int>;
using vl = vector<ll>;
using pii = pair<int, int>;
#define pb push_back
#define rep(i, a, b) for(int i = (a); i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()

const int MAX_N = 4e5 + 1;
const ll MOD = 30013;

/** 
 * DATASTRUCTURE: Segment Tree
 * PURPOSE: Range Updates and Queries
 * TIME: O(log n) to update and query
*/
template <class T> class SegmentTree {
  private:
	const T UNIT = {0, 0};

    T combine(T a, T b){
        if (a.first == b.first){
            return {a.first, (a.second + b.second) % MOD};
        }

        return max(a, b);
    }

	vector<T> segtree;
	int len;

  public:
	SegmentTree(int len) : len(len), segtree(len * 2, UNIT) {}

	void set(int ind, T val) {
		ind += len;
		segtree[ind] = val;
		for (; ind > 1; ind /= 2) {
			segtree[ind / 2] = combine(segtree[ind], segtree[ind ^ 1]);
		}
	}

    // [start, end)
	T query(int start, int end) {
		T ans = UNIT;
		for (start += len, end += len; start < end; start /= 2, end /= 2) {
			if (start % 2 == 1) { ans = combine(ans, segtree[start++]); }
			if (end % 2 == 1) { ans = combine(ans, segtree[--end]); }
		}
		return ans;
	}
};

void solve(){
    int n; cin >> n;

    vector<array<int, 4>> trapezoids(n);
    vector<int> compress;
    rep(i, 0, n){
        int a, b, c, d; cin >> a >> b >> c >> d;
        trapezoids[i] = {b, a, c, d};
        compress.pb(a);
        compress.pb(b);
        compress.pb(c);
        compress.pb(d);
    }

    sort(all(compress));
    map<int, int> mp;
    int cnt = 1;
    rep(i, 0, compress.size()){
        if (i != 0 && compress[i] != compress[i - 1]){
            cnt++;
        }

        mp[compress[i]] = cnt;
    }

    rep(i, 0, n){
        rep(j, 0, 4){
            trapezoids[i][j] = mp[trapezoids[i][j]];
        }
    }

    sort(all(trapezoids));
    
    vector<pii> dp(n + 1, {0, 0});
    dp[n] = {0, 1};
    vector<pii> pp = dp;
    SegmentTree<pii> st(MAX_N + 1);
    st.set(MAX_N, {0, 1});

    priority_queue<pii> pq;

    for (int i = n - 1; i >= 0; i--){
        array<int, 4> t = trapezoids[i];

        while(!pq.empty() && pq.top().first > t[0]){
            int j = pq.top().second;
            pq.pop();
            
            st.set(trapezoids[j][2], pp[j]);
        }

        pii a = st.query(t[3] + 1, MAX_N + 1);
        a.first++;
        pii o = dp[i + 1];

        pp[i] = a;

        if (a.first == o.first){
            dp[i] = o;
            dp[i].second += a.second;
            dp[i].second %= MOD;
        } else {
            dp[i] = max(a, o);
        }
        
        pq.push({t[1], i});
    }

    cout << dp[0].first << " " << dp[0].second << endl;
}

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    solve();
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...