이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
// JOIOC 2016, Selling RNA Strands
#include <bits/stdc++.h>
using namespace std;
void main_program();
signed main(){
ios_base::sync_with_stdio(0); cin.tie(0);
main_program();
}
using ii = pair<int, int>;
inline int convert(char c){
if (c == 'A') return 0;
if (c == 'G') return 1;
if (c == 'C') return 2;
return 3;
}
struct Trie{
Trie* child[4];
vector<int> nodes;
Trie() {
for (int i = 0; i < 4; i++) child[i] = nullptr;
}
void add(const string &s, int num, int i = 0){
if (i >= (int)s.size()){
nodes.push_back(num);
return;
}
int c = convert(s[i]);
if (!child[c]) child[c] = new Trie();
child[c]->add(s, num, i+1);
}
void dfs(int &timer, vector<int> &s, vector<ii> &q){
for (auto node: nodes){
if (node < 0) q[-node-1].first = timer;
}
for (auto node: nodes){
if (node >= 0) s[node] = timer++;
}
for (int c = 0; c < 4; c++){
if (child[c]) child[c]->dfs(timer, s, q);
}
for (auto node: nodes){
if (node < 0) q[-node-1].second = timer;
}
}
};
vector<int> combine(const vector<int> &A, const vector<int> &B){
int itA = 0, itB = 0;
vector<int> v;
while (itA < (int)A.size() && itB < (int)B.size()){
if (A[itA] < B[itB]){
v.push_back(A[itA]);
itA++;
}
else{
v.push_back(B[itB]);
itB++;
}
}
while (itA < (int)A.size()){
v.push_back(A[itA]);
itA++;
}
while (itB < (int)B.size()){
v.push_back(B[itB]);
itB++;
}
return v;
}
int count(vector<int> &V, int L, int R){
int ansR = upper_bound(V.begin(), V.end(), R) - V.begin();
int ansL = lower_bound(V.begin(), V.end(), L) - V.begin();
return ansR - ansL;
}
struct MergeSortTree{
vector<vector<int>> tree;
int _n;
MergeSortTree() {}
MergeSortTree(int N): tree(4 * N), _n(N) {}
MergeSortTree(vector<int> &V): MergeSortTree(V.size()) {
build(1, 0, _n - 1, V);
}
void build(int i, int l, int r, vector<int> &V){
if (l == r) tree[i] = {V[l]};
else{
int mid = (l + r) >> 1;
build(i<<1, l, mid, V);
build(i<<1|1, mid+1, r, V);
tree[i] = combine(tree[i<<1], tree[i<<1|1]);
}
}
int get(int tl, int tr, int L, int R) { return get(1, 0, _n - 1, tl, tr, L, R); }
int get(int i, int l, int r, int tl, int tr, int L, int R){
if (tl <= l && r <= tr){
return count(tree[i], L, R);
}
if (tl > r || tr < l) return 0;
int mid = (l + r) >> 1;
int resx = get(i<<1, l, mid, tl, tr, L, R);
int resy = get(i<<1|1, mid+1, r, tl, tr, L, R);
return resx + resy;
}
};
int n, q;
vector<string> vs;
vector<pair<string, string>> qs;
void main_program(){
cin >> n >> q;
vs.resize(n);
qs.resize(q);
for (int i = 0; i < n; i++) cin >> vs[i];
for (int i = 0; i < q; i++) cin >> qs[i].first >> qs[i].second;
vector<int> idxP(n), idxQ(n);
vector<ii> qP(q), qQ(q);
{
for (auto &s: vs) reverse(s.begin(), s.end());
Trie root;
for (int i = 0; i < n; i++){
root.add(vs[i], i);
}
for (int i = 0; i < q; i++){
string qq = qs[i].second;
reverse(qq.begin(), qq.end());
root.add(qq, -i-1);
}
int timer = 0;
root.dfs(timer, idxQ, qQ);
}
{
for (auto &s: vs) reverse(s.begin(), s.end());
Trie root;
for (int i = 0; i < n; i++){
root.add(vs[i], i);
}
for (int i = 0; i < q; i++){
string pp = qs[i].first;
root.add(pp, -i-1);
}
int timer = 0;
root.dfs(timer, idxP, qP);
}
vector<int> V(n);
for (int i = 0; i < n; i++) V[idxP[i]] = idxQ[i];
MergeSortTree st(V);
for (int i = 0; i < q; i++){
if (qP[i].first >= qP[i].second) cout << "0\n";
else if (qQ[i].first >= qQ[i].second) cout << "0\n";
else cout << st.get(qP[i].first, qP[i].second - 1, qQ[i].first, qQ[i].second - 1) << "\n";
}
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |