Submission #196376

# Submission time Handle Problem Language Result Execution time Memory
196376 2020-01-17T04:05:21 Z darkkcyan Selling RNA Strands (JOI16_selling_rna) C++17
35 / 100
1500 ms 1048580 KB
// 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;
}

Compilation message

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 time Memory Grader output
1 Correct 20 ms 18552 KB Output is correct
2 Correct 20 ms 18680 KB Output is correct
3 Correct 20 ms 18680 KB Output is correct
4 Correct 20 ms 18552 KB Output is correct
5 Correct 20 ms 18636 KB Output is correct
6 Correct 19 ms 18556 KB Output is correct
7 Correct 16 ms 18552 KB Output is correct
# Verdict Execution time Memory Grader output
1 Runtime error 1515 ms 1048580 KB Execution killed with signal 9 (could be triggered by violating memory limits)
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 102 ms 30244 KB Output is correct
2 Correct 106 ms 33016 KB Output is correct
3 Correct 111 ms 31992 KB Output is correct
4 Correct 91 ms 29560 KB Output is correct
5 Correct 101 ms 31008 KB Output is correct
6 Correct 107 ms 30968 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 20 ms 18552 KB Output is correct
2 Correct 20 ms 18680 KB Output is correct
3 Correct 20 ms 18680 KB Output is correct
4 Correct 20 ms 18552 KB Output is correct
5 Correct 20 ms 18636 KB Output is correct
6 Correct 19 ms 18556 KB Output is correct
7 Correct 16 ms 18552 KB Output is correct
8 Runtime error 1515 ms 1048580 KB Execution killed with signal 9 (could be triggered by violating memory limits)
9 Halted 0 ms 0 KB -