Submission #839481

#TimeUsernameProblemLanguageResultExecution timeMemory
839481CDuongSelling RNA Strands (JOI16_selling_rna)C++17
100 / 100
171 ms194368 KiB
/*
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx2,fma,bmi,bmi2,sse4.2,popcnt,lzcnt")
*/

#include <bits/stdc++.h>
#define taskname ""
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define ll long long
#define ld long double
#define pb push_back
#define ff first
#define ss second
#define pii pair<int, int>
#define vi vector<int>
#define vii vector<pii>
#define isz(x) (int)x.size()
using namespace std;

const int mxN = 2e5 + 5;
const int mod = 1e9 + 7;
const ll oo = 1e18;

struct node {
    int l, r;
    node *nxt[4];
    vi idx;
};

struct Op {
    int x, y, idx;
    Op(int x, int y, int idx) : x(x), y(y), idx(idx) {}

    bool operator < (const Op &o) const {
        return x < o.x;
    }
};

struct FenwickTree {
    int n;
    vi data;

    FenwickTree(int n) : n(n), data(n + 1) {}

    void update(int idx, int val) {
        while (idx <= n) {
            data[idx] += val;
            idx += idx & -idx;
        }
    }

    int get(int idx) {
        int res = 0;
        while (idx) {
            res += data[idx];
            idx -= idx & -idx;
        }
        return res;
    }
};

array<int, 2> points[mxN];
int n, q, ans[mxN], enc[256], cc;
node *root1 = new node();
node *root2 = new node();

void add(string &s, int idx) {
    node *cur = root1;
    for (char c : s) {
        int ch = enc[(int)c];
        if (!cur->nxt[ch]) {
            cur->nxt[ch] = new node();
        }
        cur = cur->nxt[ch];
    }
    cur->idx.emplace_back(idx);

    cur = root2;
    reverse(all(s));
    for (char c : s) {
        int ch = enc[(int)c];
        if (!cur->nxt[ch]) {
            cur->nxt[ch] = new node();
        }
        cur = cur->nxt[ch];
    }
    cur->idx.emplace_back(idx);
}

void dfs(node *cur, int idx) {
    cur->l = cc;
    for (int val : cur->idx)
        points[val][idx] = cc++;
    for (int i = 0; i < 4; ++i) {
        if (cur->nxt[i]) {
            dfs(cur->nxt[i], idx);
        }
    }
    cur->r = cc - 1;
}

pii get(string &s, node *cur) {
    for (char c : s) {
        int ch = enc[(int)c];
        if (!cur->nxt[ch]) {
            return pair{-1, -1};
        }
        cur = cur->nxt[ch];
    }
    return pair{cur->l, cur->r};
}

void solve() {
    cin >> n >> q;
    for (int i = 1; i <= n; ++i) {
        string s; cin >> s;
        add(s, i);
    }

    cc = 1; dfs(root1, 0);
    cc = 1; dfs(root2, 1);
    sort(points + 1, points + n + 1);

    vector<Op> op;
    auto addRange = [&](int x1, int x2, int y1, int y2, int idx) -> void {
        op.emplace_back(x2, y2, idx);
        op.emplace_back(x1 - 1, y2, -idx);
        op.emplace_back(x2, y1 - 1, -idx);
        op.emplace_back(x1 - 1, y1 - 1, idx);
    };

    for (int i = 1; i <= q; ++i) {
        string pfx, sfx;
        cin >> pfx >> sfx;
        reverse(all(sfx));
        pii x = get(pfx, root1);
        pii y = get(sfx, root2);
        if (x.ff == -1 || y.ff == -1) {
            ans[i] = 0;
        }
        else {
            addRange(x.ff, x.ss, y.ff, y.ss, i);
        }
        // cout << x.ff << " " << x.ss << " " << y.ff << " " << y.ss << endl;
    }
    sort(all(op));

    FenwickTree fenw(n);
    int ptr = 1;
    for (auto &[x, y, idx] : op) {
        while (ptr <= n && points[ptr][0] <= x) {
            fenw.update(points[ptr][1], 1);
            ++ptr;
        }
        ans[abs(idx)] += fenw.get(y) * (idx > 0 ? 1 : -1);
    }

    for (int i = 1; i <= q; ++i) {
        cout << ans[i] << "\n";
    }
}

signed main() {

#ifndef CDuongg
    if(fopen(taskname".inp", "r"))
        assert(freopen(taskname".inp", "r", stdin)), assert(freopen(taskname".out", "w", stdout));
#else
    freopen("bai3.inp", "r", stdin);
    freopen("bai3.out", "w", stdout);
    auto start = chrono::high_resolution_clock::now();
#endif

    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    enc['A'] = 0;
    enc['C'] = 1;
    enc['G'] = 2;
    enc['U'] = 3;
    int t = 1; //cin >> t;
    while(t--) solve();

#ifdef CDuongg
   auto end = chrono::high_resolution_clock::now();
   cout << "\n"; for(int i = 1; i <= 100; ++i) cout << '=';
   cout << "\nExecution time: " << chrono::duration_cast<chrono::milliseconds> (end - start).count() << "[ms]" << endl;
#endif

}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...