#include <bits/stdc++.h>
using namespace std;
template <typename T1, typename T2> istream &operator>>(istream &is, pair<T1, T2> &pa) { is >> pa.first >> pa.second; return is; }
template <typename T> istream &operator>>(istream &is, vector<T> &vec) { for (auto &v : vec) is >> v; return is; }
template <typename T1, typename T2> ostream &operator<<(ostream &os, const pair<T1, T2> &pa) { os << "(" << pa.first << "," << pa.second << ")"; return os; }
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) { os << "["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template <typename T> ostream &operator<<(ostream &os, const deque<T> &vec) { os << "deq["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template <typename T> ostream &operator<<(ostream &os, const set<T> &vec) { os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template <typename T> ostream &operator<<(ostream &os, const multiset<T> &vec) { os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template <typename T> ostream &operator<<(ostream &os, const unordered_set<T> &vec) { os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template <typename T> ostream &operator<<(ostream &os, const unordered_multiset<T> &vec) { os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template <typename TK, typename TV> ostream &operator<<(ostream &os, const unordered_map<TK, TV> &mp) { os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
template <typename TK, typename TV> ostream &operator<<(ostream &os, const map<TK, TV> &mp) { os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
template <typename T> void resize_array(vector<T> &vec, int len) { vec.resize(len); }
template <typename T, typename... Args> void resize_array(vector<T> &vec, int len, Args... args) { vec.resize(len); for (auto &v : vec) resize_array(v, args...); }
template <typename T1, typename T2> pair<T1, T2> operator+(const pair<T1, T2> &l, const pair<T1, T2> &r) { return make_pair(l.first + r.first, l.second + r.second); }
template <typename T1, typename T2> pair<T1, T2> operator-(const pair<T1, T2> &l, const pair<T1, T2> &r) { return make_pair(l.first - r.first, l.second - r.second); }
long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x; }
// 函数名后面加 ll 就可以计算 long long类型对应的结果
// __builtin_ffs(x) // 返回x中最后一个为1的位是从后向前的第几位
// __builtin_popcount(x) // x中1的个数
// __builtin_ctz(x) // x末尾0的个数。x=0时结果未定义。
// __builtin_clz(x) // x前导0的个数。x=0时结果未定义。
// __builtin_parity(x) // x中1的奇偶性。
#define highest_bit1_index(x) (31 - __builtin_clz(x))
#define highest_bit1_index_ll(x) (63 - __builtin_clzll(x))
#define rep(i, a, n) for (int i = a; i < (n); i++)
#define per(i, a, n) for (int i = (n)-1; i >= a; i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define sz(x) ((int)(x).size())
typedef vector<int> vi;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef double db;
#if DEBUG
#define dbg(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ") " << __FILE__ << endl;
#else
#define dbg(x)
#endif
// For example: SegmentTree<int> st(n, [](int a, int b) { return max(a, b); });
template <typename T>
class SegmentTree {
public:
SegmentTree(int node_num, function<T(T, T)> f, T default_v = T())
: f_(f), default_value_(default_v) {
node_num_ = node_num;
offset_ = 1;
while (offset_ < node_num) offset_ *= 2;
nodes_.resize(offset_ * 2, default_v);
}
friend istream& operator>>(istream& in, SegmentTree<T>& st) {
for (int i = 0; i < st.node_num_; ++i) {
cin >> st.nodes_[i + st.offset_ - 1];
}
return in;
}
// Init 前需要先赋初始值给nodes_
// rep(i,0,n) {
// nodes_[i + offset_ - 1] = A[i];
// }
void Init() {
for (int k = offset_ - 2; k >= 0; --k) {
nodes_[k] = f_(nodes_[k * 2 + 1], nodes_[k * 2 + 2]);
}
}
// 将第k个值更新为a
void Update(int k, T a) {
// 叶子节点
k += offset_ - 1;
nodes_[k] = a;
// 向上更新
while (k > 0) {
k = (k - 1) / 2;
nodes_[k] = f_(nodes_[k * 2 + 1], nodes_[k * 2 + 2]);
}
}
// 迭代写法,效率更高(多找几道题验证下)
// T Query(int lo, int hi) {
// T ra = default_value_, rb = default_value_;
// for (lo += offset_ - 1, hi += offset_ - 1; lo < hi; lo /= 2, hi /= 2) {
// if (!(lo & 1)) ra = f_(ra, nodes_[lo++]);
// if (!(hi & 1)) rb = f_(rb, nodes_[--hi]);
// }
// return f_(ra, rb);
// }
// 递归写法,更好理解
T Query(int a, int b) { return Query(a, b, 0, 0, offset_); }
private:
// 求[a,b)区间的目标值
// 后面的参数是为了计算方便传入的
// k是节点的编号,l,r表示这个节点代表区间[l,r)
// 外部调用时,使用query(a,b,0,0,n);
T Query(int a, int b, int k, int l, int r) {
// 如果[a,b)和[l,r)不相交,返回0
if (r <= a || b <= l) return default_value_;
// 如果[a,b)完全包含[l,r),返回当前节点值
if (a <= l && r <= b)
return nodes_[k];
else {
T v1 = Query(a, b, k * 2 + 1, l, (l + r) / 2);
T v2 = Query(a, b, k * 2 + 2, (l + r) / 2, r);
return f_(v1, v2);
}
}
int node_num_;
int offset_;
vector<T> nodes_;
function<T(T, T)> f_;
T default_value_;
};
constexpr int MOD = 30013;
class Solution {
struct Line {
int up,down;
bool is_left;
int id;
pii max_independent_set = mp(0, 0);
friend ostream& operator<<(ostream& os, const Line& line) {
os << "[" << (line.is_left ? "L" : "R") << "](" << line.up << "," << line.down << ")";
return os;
}
bool operator<(const Line& other) const {
return down == other.down ? up < other.up : down < other.down;
}
};
public:
void Solve() {
int n;
while(cin>>n) {
// 存储梯形的坐标信息
// 每个梯形由两个点对表示:{{左上,左下}, {右上,右下}}
vector<Line> trapezoids;
set<int> coordinates;
// 读入n个梯形的坐标
for (int i = 0; i < n; i++) {
int upper_left, upper_right; // 上边两端点的x坐标
int bottom_left, bottom_right; // 下边两端点的x坐标
cin >> upper_left >> upper_right >> bottom_left >> bottom_right;
coordinates.insert(upper_left);
coordinates.insert(upper_right);
coordinates.insert(bottom_left);
coordinates.insert(bottom_right);
trapezoids.push_back({upper_left, bottom_left, true, i});
trapezoids.push_back({upper_right, bottom_right, false, i});
}
map<int, int> cordinate_compress;
int i = 0;
for (auto x : coordinates) {
cordinate_compress[x] = i++;
}
sort(trapezoids.begin(), trapezoids.end());
map<int, int> right_line_id_to_index;
for(int i = 0; i < trapezoids.size(); i++) {
if(!trapezoids[i].is_left) {
right_line_id_to_index[trapezoids[i].id] = i;
}
}
SegmentTree<pii> st(coordinates.size(), [](pii a, pii b) {
if (a.first > b.first) return a;
else if (a.first < b.first) return b;
else return mp(a.first, (a.second + b.second) % MOD);
}, mp(0, 0));
pii ans = mp(0, 0);
for(int i = 0; i < trapezoids.size(); i++) {
if(trapezoids[i].is_left) {
pii ret = st.Query(0, cordinate_compress[trapezoids[i].up]);
if (ret.second == 0) ret.second = 1;
ret.first = ret.first + 1;
auto& right_line = trapezoids[right_line_id_to_index[trapezoids[i].id]];
right_line.max_independent_set = ret;
if (ret.first > ans.first) ans = ret;
else if (ret.first == ans.first) ans.second = (ans.second + ret.second) % MOD;
} else {
auto& right_line = trapezoids[i];
st.Update(cordinate_compress[right_line.up], right_line.max_independent_set);
}
}
// 输出所有梯形的坐标信息
cout << ans.first << " " << ans.second << endl;
}
cout.flush();
}
private:
};
// # define FILE_IO 1
void set_io(const string &name = "") {
ios::sync_with_stdio(false);
cin.tie(nullptr);
#if FILE_IO
if (!name.empty()) {
freopen((name + ".in").c_str(), "r", stdin);
freopen((name + ".out").c_str(), "w", stdout);
}
#endif
}
int main() {
// cout << max(mp(4,0), mp(4,100)) << endl;
set_io("tmp");
Solution().Solve();
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |