Submission #1131464

#TimeUsernameProblemLanguageResultExecution timeMemory
1131464RedGrey1993Zoltan (COCI16_zoltan)C++20
140 / 140
262 ms13352 KiB
#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; if (nodes_[k].first == a.first) nodes_[k].second += a.second; else nodes_[k] = a; // 向上更新 while (k > 0) { k = (k - 1) / 2; nodes_[k] = f_(nodes_[k * 2 + 1], nodes_[k * 2 + 2]); } } // 迭代写法,效率更高(多找几道题验证下) // https://oj.uz/problem/view/balkan11_trapezoid 验证通过 迭代耗时:366 ms,递归耗时:379 ms // https://www.spoj.com/problems/QTREE/ 验证通过 迭代耗时:400 ms,递归耗时:700 ms // 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_; }; // Right: -Mint(1), Wrong: Mint(-1) !!! template <unsigned int MOD> class ModInt { public: ModInt(unsigned long long _v = 0) { set_v((_v % MOD + MOD)); } explicit operator bool() const { return val != 0; } ModInt operator-() const { return ModInt() - *this; } ModInt operator+(const ModInt &r) const { return ModInt().set_v(val + r.val); } ModInt operator-(const ModInt &r) const { return ModInt().set_v(val + MOD - r.val); } ModInt operator*(const ModInt &r) const { return ModInt().set_v((unsigned int)((unsigned long long)(val)*r.val % MOD)); } ModInt operator/(const ModInt &r) const { return *this * r.inv(); } ModInt &operator+=(const ModInt &r) { return *this = *this + r; } ModInt &operator-=(const ModInt &r) { return *this = *this - r; } ModInt &operator*=(const ModInt &r) { return *this = *this * r; } ModInt &operator/=(const ModInt &r) { return *this = *this / r; } // ModInt &operator=(unsigned long long _v) { set_v((_v % MOD + MOD)); return *this; } unsigned int operator=(unsigned long long _v) { set_v((_v % MOD + MOD)); return val; } bool operator==(const ModInt &r) const { return val == r.val; } bool operator!=(const ModInt &r) const { return val != r.val; } ModInt pow(long long n) const { ModInt x = *this, r = 1; while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; } ModInt inv() const { return pow(MOD - 2); } friend ostream &operator<<(ostream &os, const ModInt &r) { return os << r.val; } friend istream &operator>>(istream &is, ModInt &r) { return is >> r.val; } private: unsigned int val; ModInt &set_v(unsigned int _v) { val = (_v < MOD) ? _v : _v - MOD; return *this; } }; using Mint = ModInt<(unsigned int)(1e9+7)>; class Solution { public: void Solve() { int n; while(cin>>n) { vector<int> a(n); cin>>a; // 路径压缩 vector<int> b = a; sort(all(b)); b.erase(unique(all(b)), b.end()); for(int i = 0; i < n; i++) { a[i] = lower_bound(all(b), a[i]) - b.begin(); assert(a[i] >= 0 && a[i] < n); } vector<pair<int,Mint>> ans1(n),ans2(n); SegmentTree<pair<int,Mint>> st1(n, [](const pair<int,Mint>& a, const pair<int,Mint>& 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); }, mp(0,0)); per(i,0,n) { auto max_len = st1.Query(a[i]+1, n); if (max_len.first == 0) max_len.second = 1; max_len.first++; ans1[i] = max_len; st1.Update(a[i], max_len); } SegmentTree<pair<int,Mint>> st2(n, [](const pair<int,Mint>& a, const pair<int,Mint>& 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); }, mp(0,0)); per(i,0,n) { auto max_len = st2.Query(0, a[i]); if (max_len.first == 0) max_len.second = 1; max_len.first++; ans2[i] = max_len; st2.Update(a[i], max_len); } int max_l = 0; Mint max_cnt = 0; rep(i,0,n) { if (ans1[i].first + ans2[i].first - 1 > max_l) { max_l = ans1[i].first + ans2[i].first - 1; max_cnt = ans1[i].second * ans2[i].second * Mint(2).pow(n - max_l); } else if (ans1[i].first + ans2[i].first - 1 == max_l) { max_cnt = (max_cnt + ans1[i].second * ans2[i].second * Mint(2).pow(n - max_l)); } } cout << max_l << " " << max_cnt << "\n"; } 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() { set_io("tmp"); Solution().Solve(); return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...