제출 #196376

#제출 시각아이디문제언어결과실행 시간메모리
196376darkkcyanSelling RNA Strands (JOI16_selling_rna)C++17
35 / 100
1515 ms1048580 KiB
// vim: foldmethod=marker // Thu Jan 16 21:39:21 MSK 2020: START coding #include <bits/stdc++.h> using namespace std; #define llong long long #define len(x) ((int)x.size()) #define rep(i,n) for (int i = -1; ++ i < n; ) #define rep1(i,n) for (int i = 0; i ++ < n; ) #define rand __rand mt19937 rng(chrono::system_clock::now().time_since_epoch().count()); // or mt19937_64 template<class T = int> T rand(T range = numeric_limits<T>::max()) { return (T)(rng() % range); } /*{{{*/ #define CONCAT_(x, y) x##y #define CONCAT(x, y) CONCAT_(x, y) #ifdef LOCAL_DEBUG int debug = 1; #define DB(...) stringstream CONCAT(ss, __LINE__); CONCAT(ss, __LINE__) << __VA_ARGS__; debug_block CONCAT(dbbl, __LINE__)(CONCAT(ss, __LINE__).str()) #else int debug = 0; #define DB(...) #endif int __db_level = 0; #define clog if (debug) cerr << string(__db_level * 2, ' ') struct debug_block { string name; debug_block(const string& name_): name(name_) { clog << "{ " << name << endl; ++__db_level; } ~debug_block() { --__db_level; clog << "} " << name << endl; } }; #define deb(...) "[" << #__VA_ARGS__ << "] = [" << __VA_ARGS__ << "]" #define debln(...) clog << "[" << #__VA_ARGS__ << "] = [" << __VA_ARGS__ << "]" << endl #define _ << ", " << template<class U, class V> ostream& operator<<(ostream& out, const pair<U, V>& p) { return out << "(" << p.first _ p.second << ")"; } template<class A, class B> ostream& operator<<(ostream& out, const tuple<A, B>& t) { return out << "(" << get<0>(t) _ get<1>(t) << ")"; } template<class A, class B, class C> ostream& operator<<(ostream& out, const tuple<A, B, C>& t) { return out << "(" << get<0>(t) _ get<1>(t) _ get<2>(t) << ")"; } template<class T> ostream& operator<<(ostream& out, const vector<T>& container) { out << "{"; if (len(container)) out << container[0]; rep1(i, len(container) - 1) out _ container[i]; return out << "}"; } template<class x> vector<typename x::value_type> $v(const x& a) { return vector<typename x::value_type>(a.begin(), a.end()); } #define ptrtype(x) typename iterator_traits<x>::value_type template<class u> vector<ptrtype(u)> $v(u a, u b) { return vector<ptrtype(u)>(a, b); } /*}}}*/ // ACTUAL SOLUTION BELOW //////////////////////////////////////////////////////////// const int maxn = 101010; unordered_map<char, char> char_map = { {'A', 0}, {'C', 1}, {'G', 2}, {'U', 3} }; vector<char> transform_rna(const string s) { vector<char> ans(len(s)); rep(i, len(s)) ans[i] = char_map[s[i]]; return ans; } template<class container> struct trie { trie* child[4]; int cnt; int cnt_all; trie(): child{0}, cnt(0), cnt_all(0) {} ~trie() { rep(i, 4) if(child[i]) delete child[i]; } void insert(const container& s) { trie* cur = this; for (auto i: s) { if (!cur->child[(int)i]) cur->child[(int)i] = new trie(); cur = cur->child[(int)i]; ++cur->cnt_all; } cur->cnt++; } // return (lower_bound, cnt) pair<int, int> find_bound(const container& s) { DB("find_bound"); debln(s); int cnt_lower = 0; trie* cur = this; for (auto i: s) { cnt_lower += cur->cnt; rep(f, i) if (cur->child[f]) cnt_lower += cur->child[f]->cnt_all; debln(cur->child[(int)i]); debln(cnt_lower); if (!cur->child[(int)i]) return {cnt_lower, 0}; cur = cur->child[(int)i]; debln(cur->cnt _ cur->cnt_all); } return {cnt_lower, cur->cnt_all}; } }; using trie_char = trie<vector<char>>; int n, m; vector<char> a[maxn]; trie_char it[maxn * 4]; void it_insert(const vector<char>& what, int pos, int i = 1, int l = 0, int r = n) { if (pos < l or pos >= r) return ; it[i].insert(what); if (r - l <= 1) return ; int mid = (l + r) / 2; it_insert(what, pos, i << 1, l, mid); it_insert(what, pos, i << 1 | 1, mid, r); } int it_count(const vector<char>& what, int from, int to, int i = 1, int l = 0, int r = n) { if (l >= to or from >= r) return 0; if (from <= l and r <= to) { auto [lower, cnt] = it[i].find_bound(what); return cnt; } int mid = (l + r) / 2; return it_count(what, from, to, i << 1, l, mid) + it_count(what, from, to, i << 1 | 1, mid, r); } int main(void) { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n >> m; rep(i, n) { string s; cin >> s; a[i] = transform_rna(s); } trie_char root; rep(i, n) { root.insert(a[i]); a[i].clear(); } // in other words, this part is "sorting". vector<pair<trie_char*, int>> qu; // well it can be a queue, but stack is fine. for (qu.emplace_back(&root, 0); len(qu); ) { auto [cur_root, cnt_lower] = qu.back(); qu.pop_back(); cnt_lower += cur_root->cnt; rep(i, 4) { if (!cur_root->child[i]) continue; qu.emplace_back(cur_root->child[i], cnt_lower); rep(f, cur_root->child[i]->cnt_all) { a[f + cnt_lower].push_back((char)i); } cnt_lower += cur_root->child[i]->cnt_all; } } debln($v(a, a + n)); rep(i, n) { reverse(a[i].begin(), a[i].end()); it_insert(a[i], i); } rep(query, m) { DB(deb(query)); string pref, suff; cin >> pref >> suff; auto tr_pref = transform_rna(pref), tr_suff = transform_rna(suff); reverse(tr_suff.begin(), tr_suff.end()); auto bound = root.find_bound(tr_pref); debln(bound); auto ans = it_count(tr_suff, bound.first, bound.first + bound.second); cout << ans << '\n'; } return 0; }

컴파일 시 표준 에러 (stderr) 메시지

selling_rna.cpp: In function 'int it_count(const std::vector<char>&, int, int, int, int, int)':
selling_rna.cpp:126:25: warning: unused variable 'lower' [-Wunused-variable]
         auto [lower, cnt] = it[i].find_bound(what);
                         ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...