Submission #1343406

#TimeUsernameProblemLanguageResultExecution timeMemory
1343406Born_To_LaughSelling RNA Strands (JOI16_selling_rna)C++17
35 / 100
113 ms68512 KiB
// Born_To_Laugh - Hughie Do
#include <bits/stdc++.h>
#define alle(AC) AC.begin(), AC.end()
#define fi first
#define se second
using namespace std;
typedef long long ll;
[[maybe_unused]] const int MOD = 998244353, INF = 1e9 + 7;

//fen
struct Fen
{
    int n;
    vector<int> bit;
    void init(int len){
        n = len;
        bit.assign(n + 1, 0);
    }
    void upd(int pos, int val){
        for(; pos<=n; pos += pos & -pos) bit[pos] += val;
    }
    int qr(int pos){
        int ans = 0;
        for(; pos>0; pos -= pos & -pos) ans += bit[pos];
        return ans;
    }
};

//var
const int maxn = 2e5 + 10;
int n, q;
string inp[maxn];
int tin1[maxn], tin2[maxn], tout1[maxn], tout2[maxn];
Fen ft;
int eul1 = 0, eul2 = 0;

//trie
struct node
{
    int cnt;
    array<int, 4> child;
    node(){
        cnt = 0;
        child.fill(-1);
    }
};
vector<node> tree1(2);
vector<node> tree2(2); //rev
int id1 = 1, id2 = 1;
int new_node1(){
    id1++;
    if(id1 >= tree1.size()) tree1.push_back(node());
    return id1;
}
int new_node2(){
    id2++;
    if(id2 >= tree2.size()) tree2.push_back(node());
    return id2;
}
void add(string a){
    int pos1 = 1;
    for(int i=0; i<a.size(); ++i){
        int x = a[i];
        if(tree1[pos1].child[x - '0'] == -1){
            tree1[pos1].child[x - '0'] = new_node1();
        }
        pos1 = tree1[pos1].child[x - '0'];
    }
    tree1[pos1].cnt++;

    int pos2 = 1;
    for(int i = a.size() - 1; i>=0; --i){
        int x = a[i];
        if(tree2[pos2].child[x - '0'] == -1){
            tree2[pos2].child[x - '0'] = new_node2();
        }
        pos2 = tree2[pos2].child[x - '0'];
    }
    tree2[pos2].cnt++;
}
pair<int, int> address(string a){
    int pos1 = 1;
    for(int i=0; i<a.size(); ++i){
        int x = a[i];
        pos1 = tree1[pos1].child[x - '0'];
    }

    int pos2 = 1;
    for(int i = a.size() - 1; i>=0; --i){
        int x = a[i];
        pos2 = tree2[pos2].child[x - '0'];
    }

    return make_pair(tin1[pos1], tin2[pos2]);
}

void dfs1(int a){
    tin1[a] = ++eul1;
    for(int i=0; i<4; ++i){
        if(tree1[a].child[i] != -1) dfs1(tree1[a].child[i]);
    }
    tout1[a] = eul1;
}
void dfs2(int a){
    tin2[a] = ++eul2;
    for(int i=0; i<4; ++i){
        if(tree2[a].child[i] != -1) dfs2(tree2[a].child[i]);
    }
    tout2[a] = eul2;
}

string trans(string a){
    string nxt = "";
    for(int j=0; j<a.size(); ++j){
        if(a[j] == 'A') nxt += '0';
        else if(a[j] == 'U') nxt += '1';
        else if(a[j] == 'G') nxt += '2';
        else if(a[j] == 'C') nxt += '3';
    }
    return nxt;
}
//

int cntoqr = 0;
vector<int> upda[maxn]; // y that have to upd with x = i
vector<pair<int, int>> oqr[maxn]; // {y, id} for qr have x = i
int anoqr[maxn]; // ans for ofqr i

//anoqr[bb] - anoqr[ba] - anoqr[ab] + anoqr[aa]
struct queries
{
    int ab, ba, aa, bb;
    queries(){
        ab = ba = aa = bb = -INF;
    }
    void init(int x1, int x2, int y1, int y2){
        bb = ++cntoqr;
        ab = ++cntoqr;
        ba = ++cntoqr;
        aa = ++cntoqr;

        oqr[x2].push_back({y2, bb});
        oqr[x1 - 1].push_back({y2, ab});
        oqr[x2].push_back({y1 - 1, ba});
        oqr[x1 - 1].push_back({y1 - 1, aa});
    }
};
vector<queries> qrs;

void ope(string p, string q){
    int pos1 = 1;
    for(int i=0; i<p.size(); ++i){
        int x = p[i];
        if(tree1[pos1].child[x - '0'] == -1){
            qrs.push_back(queries());
            return;
        }
        pos1 = tree1[pos1].child[x - '0'];
    }

    int pos2 = 1;
    for(int i = q.size() - 1; i>=0; --i){
        int x = q[i];
        if(tree2[pos2].child[x - '0'] == -1){
            qrs.push_back(queries());
            return;
        }
        pos2 = tree2[pos2].child[x - '0'];
    }
    queries cc;
    cc.init(tin1[pos1], tout1[pos1], tin2[pos2], tout2[pos2]);
    qrs.push_back(cc);
}

void solve(){
    cin >> n >> q;
    for(int i=1; i<=n; ++i){
        cin >> inp[i];
        inp[i] = trans(inp[i]);
        add(inp[i]);
    }
    
    dfs1(1);
    dfs2(1);

    ft.init(eul2);

    for(int i=1; i<=n; ++i){
        pair<int, int> x = address(inp[i]);
        upda[x.fi].push_back(x.se);
    }

    while(q--){
        string p, q;cin >> p >> q;
        ope(trans(p), trans(q));
    }
    for(int i=1; i<=eul1; ++i){
        for(auto &elm: upda[i]) ft.upd(elm, 1);
        for(auto &elm: oqr[i]){
            anoqr[elm.se] = ft.qr(elm.fi);
        }
    }

    for(auto &elm: qrs){
        if(elm.bb == -INF){
            cout << 0 << '\n';
        }
        else{
            int ans = anoqr[elm.bb] - anoqr[elm.ba] - anoqr[elm.ab] + anoqr[elm.aa];
            cout << ans << '\n';
        }
    }
}
signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...