QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#83983#2135. How Many Strings Are LessZuqa#WA 13ms26924kbC++207.4kb2023-03-04 20:09:272023-03-04 20:09:31

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-03-04 20:09:31]
  • 评测
  • 测评结果:WA
  • 用时:13ms
  • 内存:26924kb
  • [2023-03-04 20:09:27]
  • 提交

answer

#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

#define el '\n'
#define FIO ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef complex<ld> pt;
typedef unsigned long long ull;

template<typename T, typename X>
using hashTable = gp_hash_table<T, X>;
template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template<typename T>
using ordered_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;

// mt19937_64 for long long
mt19937 rng(std::chrono::system_clock::now().time_since_epoch().count());

const int N = 1e6 + 5, P1 = 29, P2 = 31, MOD1 = 1e9 + 7, MOD2 = 1e9 + 9;
int pw1[N], inv1[N], pw2[N], inv2[N];
int prefixPW1[N], prefixPW2[N];

int add(int a, int b, int mod)
{
    return (a + b) % mod;
}

int sub(int a, int b, int mod)
{
    return ((a - b) % mod + mod) % mod;
}

int mul(int a, int b, int mod)
{
    return 1ll * a * b % mod;
}

int fp(int base, int power, int mod)
{
    if(!power)
        return 1;

    int ret = fp(base, power >> 1, mod);
    ret = mul(ret, ret, mod);

    if(power & 1)
        ret = mul(ret, base, mod);

    return ret;
}

struct Hash
{
    vector<pair<int, int>> prefix;

    Hash(const string &s)
    {
        prefix.resize(s.size() + 1);
        for(int i = 0; i < int(s.size()); ++i)
            prefix[i + 1] = make_pair(add(prefix[i].first, mul(pw1[i], s[i] - 'a' + 1, MOD1), MOD1),
                                      add(prefix[i].second, mul(pw2[i], s[i] - 'a' + 1, MOD2), MOD2));
    }

    int size() const
    {
        return prefix.size() - 1;
    }

    pair<int, int> getHash() const
    {
        return prefix.back();
    }

    pair<int, int> getRange(int l, int r) const
    {
        return make_pair(mul(inv1[l], sub(prefix[r + 1].first, prefix[l].first, MOD1), MOD1),
                         mul(inv2[l], sub(prefix[r + 1].second, prefix[l].second, MOD2), MOD2));
    }

    static void prepare()
    {
        pw1[0] = inv1[0] = pw2[0] = inv2[0] = prefixPW1[0] = prefixPW2[0] = 1;
        int iv1 = fp(P1, MOD1 - 2, MOD1);
        int iv2 = fp(P2, MOD2 - 2, MOD2);
        for(int i = 1; i < N; ++i)
        {
            pw1[i] = mul(pw1[i - 1], P1, MOD1);
            prefixPW1[i] = add(pw1[i], prefixPW1[i - 1], MOD1);

            pw2[i] = mul(pw2[i - 1], P2, MOD2);
            prefixPW2[i] = add(pw2[i], prefixPW2[i - 1], MOD2);

            inv1[i] = mul(inv1[i - 1], iv1, MOD1);
            inv2[i] = mul(inv2[i - 1], iv2, MOD2);
        }
    }
};

struct Node
{
    pair<int, int> hash;
};

struct segTree
{
    int len;
    vector<Node> tree;
    Node neutral = Node({{0, 0}});
    vector<pair<int, int>> lazy;

    segTree(int n)
    {
        len = n;
        int sz = 1;
        while(sz < n)
            sz *= 2;

        tree = vector<Node>(2 * sz);
        lazy = vector<pair<int, int>>(2 * sz, {-1, -1});
    }

    Node single(int s, int e, char val)
    {
        Node ret;
        ret.hash.first = mul(val - 'a' + 1, pw1[s], MOD1);
        ret.hash.second = mul(val - 'a' + 1, pw2[s], MOD2);
        return ret;
    }

    Node merge(Node a, Node b)
    {
        Node ret;
        ret.hash.first = add(a.hash.first, b.hash.first, MOD1);
        ret.hash.second = add(a.hash.second, b.hash.second, MOD2);
        return ret;
    }

    void propagate(int node, int s, int e)
    {
        if(lazy[node].first == -1)
            return;

        tree[node].hash.first = mul(lazy[node].first, sub(prefixPW1[e], prefixPW1[s - 1], MOD1), MOD1);
        tree[node].hash.second = mul(lazy[node].second, sub(prefixPW2[e], prefixPW2[s - 1], MOD2), MOD2);

        if(s != e)
        {
            lazy[node * 2] = lazy[node];
            lazy[node * 2 + 1] = lazy[node];
        }
        lazy[node] = {-1, -1};
    }

    void build(int node, int s, int e, string &st)
    {
        if(s == e)
        {
            tree[node] = single(s, e, st[s - 1]);
            return;
        }

        int mid = (s + e) >> 1;

        build(node * 2, s, mid, st);
        build(node * 2 + 1, mid + 1, e, st);

        tree[node] = merge(tree[node * 2], tree[node * 2 + 1]);
    }

    void update(int node, int s, int e, int l, int r, int val)
    {
        propagate(node, s, e);

        if(s > r || e < l)
            return;

        if(s >= l && e <= r)
        {
            tree[node].hash.first = mul(val, sub(prefixPW1[e], prefixPW1[s - 1], MOD1), MOD1);
            tree[node].hash.second = mul(val, sub(prefixPW2[e], prefixPW2[s - 1], MOD2), MOD2);
            if(s != e)
            {
                lazy[node * 2] = {val, val};
                lazy[node * 2 + 1] = {val, val};
            }

            lazy[node] = {-1, -1};
            return;
        }

        int mid = (s + e) >> 1;

        update(node * 2, s, mid, l, r, val);
        update(node * 2 + 1, mid + 1, e, l, r, val);

        tree[node] = merge(tree[node * 2], tree[node * 2 + 1]);
    }

    Node query(int node, int s, int e, int l, int r)
    {
        if(s > r || e < l)
            return neutral;

        propagate(node, s, e);

        if(s >= l && e <= r)
            return tree[node];

        int m = (s + e) >> 1;

        Node u = query(node * 2, s, m, l, r);
        Node v = query(node * 2 + 1, m + 1, e, l, r);

        return merge(u, v);
    }
};

bool cmp(Hash &t, segTree &st)
{
    int s = 1, e = min(st.len, t.size()), mid, res = -1;
    while(s <= e)
    {
        mid = (s + e) >> 1;

        auto A = t.getRange(0, mid - 1);
        auto B = st.query(1, 1, st.len, 1, mid).hash;
        B.first = mul(B.first, inv1[1], MOD1);
        B.second = mul(B.second, inv2[1], MOD2);

        if(A == B)
            s = mid + 1;
        else
            res = mid, e = mid - 1;
    }

    if(~res)
    {
        auto A = t.getRange(res - 1, res - 1);
        auto B = st.query(1, 1, st.len, res, res).hash;
        B.first = mul(B.first, inv1[res], MOD1);
        if(A.first > B.first)
            return false;
        return true;
    }
    if(st.len > t.size())
        return true;
    return false;
}

int getAns(vector<Hash> &v, segTree &st)
{
    int s = 0, e = v.size() - 1, mid, res = -1;
    while(s <= e)
    {
        mid = (s + e) >> 1;
        if(cmp(v[mid], st))
            s = mid + 1, res = mid;
        else
            e = mid - 1;
    }
    return res + 1;
}

void doWork()
{
    int n, q;
    string str;
    cin >> n >> q >> str;

    segTree st(str.length());
    st.build(1, 1, str.length(), str);

    vector<Hash> v;
    vector<string> x(n);
    for(int i = 0; i < n; i++)
        cin >> x[i];
    sort(x.begin(), x.end());
    for(int i = 0; i < n; i++)
        v.emplace_back(Hash(x[i]));
    for(auto &it: x)
        cout << it << '\n';
    cout << getAns(v, st) << '\n';


    char c;
    int idx;
    while(q--)
    {
        cin >> idx >> c;
        st.update(1, 1, str.length(), idx, str.length(), c - 'a' + 1);
        cout << getAns(v, st) << '\n';
    }
}

signed main()
{
    FIO
    Hash::prepare();
    int T = 1;
//    cin >> T;
    for(int i = 1; i <= T; i++)
        doWork();
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Wrong Answer
time: 13ms
memory: 26924kb

input:

4 3
anatoly
boris
anatooo
anbbbbu
anba
5 o
3 b
7 x

output:

anatooo
anba
anbbbbu
boris
0
0
2
3

result:

wrong output format Expected integer, but "anatooo" found