// #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 time | Memory | Grader output |
|---|
| Fetching results... |