Submission #1304666

#TimeUsernameProblemLanguageResultExecution timeMemory
1304666zyadhanytrapezoid (balkan11_trapezoid)C++20
100 / 100
137 ms27832 KiB
// #pragma GCC optimize ("Ofast")
// #pragma GCC target ("avx,avx2")
// #pragma GCC optimize("unroll-loops")
 
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
 
#define ll long long
#define ld long double
#define pl pair<ll, ll>
#define vi vector<ll>
#define vii vector<vi>
#define vc vector<char>
#define vcc vector<vc>
#define vp vector<pl>
#define mi map<ll,ll>
#define mc map<char,int>
#define sortx(X) sort(X.begin(),X.end());
#define all(X) X.begin(),X.end()
#define allr(X) X.rbegin(),X.rend()
#define ln '\n'
#define YES {cout << "YES\n"; return;}
#define NO {cout << "NO\n"; return;}
#define MUN {cout << "0\n"; return;}
 
const int MODE = 30013;
 
using namespace std;
 
struct query
{
    ll x, y, ty, ind;
    bool operator<(const query &q) {
        if (x != q.x) return x < q.x;
        return ty > q.ty;
    }
};

pl mrg(pl a, pl b) {
    if (a.first > b.first) return a;
    if (a.first < b.first) return b;
    a.second = (a.second + b.second) % MODE;
    return a;
};


/**
 * usage:-
 * creat tree element.
 * SegmentTree sg;
 * 
 * Functions you can use:
 * @set: set index or range to value.
 * @geteange: get value of given range.
 * @build: build tree with given vector or size.
 * 
 * make sure to look at item typedef.
 * you can change merge function to change it's oppration.
 * it you want to make change to segment work in checkLazy().
*/

typedef pl item;

class SegmentTree
{
public:
    void set(int index, pl value) {
        set(0, 0, size - 1, index, value);
    }
    item getrange(int l, int r) {
        return (getrange(0, 0, size - 1, l, r));
    }

    void build(int n) {
        size = 1;
        while (size < n)
            size *= 2;
        tree.assign(size * 2, item());
    }
private:
    int size;
    vector<item> tree;
    item merge(item &a, item &b) {
        return mrg(a, b);
    }

    void set(int m, int lx, int rx, int pos, pl val) {
        if (pos < lx || rx < pos) return;
        if (lx == rx && lx == pos)
        {
            tree[m] = merge(val, tree[m]);
            return;
        }
        int mid = (lx + rx) / 2;
        item s1, s2;
        set(m * 2 + 1, lx, mid, pos, val);
        set(m * 2 + 2, mid + 1, rx, pos, val);
        s1 = tree[m * 2 + 1], s2 = tree[m * 2 + 2];
        tree[m] = merge(s1, s2);
    }

    item getrange(int m, int lx, int rx, int l, int r) {
        if (rx < l || r < lx) return {0, 0};
        if (l <= lx && rx <= r) return (tree[m]);
        int mid = (lx + rx) / 2;
        item s1, s2;
        s1 = getrange(m * 2 + 1, lx, mid, l, r);
        s2 = getrange(m * 2 + 2, mid + 1, rx, l, r);
        return merge(s1, s2);
    }
};

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

    vi VC;
    vector<query> X;
    for (int i = 0; i < n; i++)
    {
        ll a, b, c, d;
        cin >> a >> b >> c >> d;
        VC.push_back(a);VC.push_back(b);VC.push_back(c);VC.push_back(d);
        X.emplace_back(query({a, c, 0, i}));
        X.emplace_back(query({b, d, 1, i}));
    }

    sortx(VC);
    VC.erase(unique(all(VC)), VC.end());
    auto get = [&](ll v) {
        return lower_bound(all(VC), v) - VC.begin();
    };
    
    sortx(X); 
    pl sol = {0, 1};
    SegmentTree sg;
    sg.build(VC.size()+10);
    vp V(n);
    sg.set(0, {0, 1});
    for (auto t : X) {
        ll id = t.ind;
        ll y = get(t.y);
        if (t.ty) {
            sg.set(y, V[id]);
        } else {
            V[id] = sg.getrange(0, y);
            V[id].first++;
            sol = mrg(sol, V[id]);
        }
    }

    cout << sol.first << ' ' << sol.second << '\n';
}
 
int main()
{
    ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int size = 1;
 
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
 
    // cin >> size;
    for (int i = 1; i <= size; i++) solve(i);
}
#Verdict Execution timeMemoryGrader output
Fetching results...