ZOJ-3940 E Modulo Query Ideas for the 13th Zhejiang Province Competition

Title

Give an array a, let the number X in the range of 0 to M take the modulus ai in turn, ask q times, how many Xs are there, and the result of the calculation is equivalent to asking yi.

https://zoj.pintia.cn/problem-sets/91827364500/problems/91827370044

analysis

Drain the big guy blog

If [0, M] (1) [0,M](1)[0,M ] ( 1 ) represents an interval from 1 to M, and each element i has only one element mapped to itself (for example, 5%100 == 5). Then the modulo operation can be expressed as such.

{ [ 0 , M ] ( 1 ) % A i } → { [ 0 , A i ] ( M / A i ) } + { [ 0 , M % A i ] ( 1 ) } \{ [0,M](1) \% A_i \} \rightarrow \{ [0,A_i] (M / A_i) \} + \{ [0, M \% A_i] (1) \} { [0,M](1)%Ai}{ [0,Ai](M/Ai)}+{ [0,M%Ai](1)}

In this way, each interval can be counted separately.

Specific implementation steps:

  • Use the key of the map to mark the right boundary, and the val to mark the number.
  • Initial state, insert an <m,1> in the map
  • Each time you get an ai, traverse and query all elements with key>=ai, and process the split of these intervals.

Here we need to use map iterator and delete operation.
The map's iterator is reclaimed, which means that if you delete the element pointed to by
this iterator , the iterator will become invalid.
If you are unfamiliar, you can write it stupidly:
auto et = it;
it = next(it);
mp.erase(er);
this question is actually a little bit special. The modified element must be in front of the current position, and
sometimes there will be unpredictable problems when inserted in the back.

  • Traverse the map backward, similar to doing a suffix sum. (No need, but I think the query complexity will be a bit more)
  • For each query, as long as the key is greater than or equal to qi, it means the number of elements mapped to qi.

The complexity of perceptual guessing will not be very high.
The rational consideration should be O (N log 2 N) O(Nlog^2N)O ( N l o g2 N). (One log comes from two points, one log comes from map)

Singleton code

map<int, ll> tree;

void solve(int kaseId = -1) {
    
    
    int n, m, q;
    cin >> n >> m;
    tree.clear();
    tree.emplace(m, 1);

    for (int i = 1, ai; i <= n; ++i) {
    
    
        cin >> ai; // ai >= 1
        for (auto it = tree.lower_bound(ai); it != tree.end();) {
    
    
            int key = it->first;
            ll val = it->second;

            tree.erase(it++);
            tree[ai - 1] += val * (key / ai);
            tree[key % ai] += val;
        }
    }

    ll suf = 0;
    for (auto it = tree.rbegin(); it != tree.rend(); ++it) {
    
    
        it->second += suf;
        suf = it->second;
    }

    cin >> q;
    ll ans = 0;
    for (int i = 1, qi; i <= q; ++i) {
    
    
        cin >> qi;
        ans = (ans + tree.lower_bound(qi)->second * i) % MOD;
    }

    cout << ans << endl;
}

Guess you like

Origin blog.csdn.net/Tighway/article/details/108026418