**E1. Stop Gaming (Easy Version)** **Time limit p...
Creado el: 20 de abril de 2025
Creado el: 20 de abril de 2025
E1. Stop Gaming (Easy Version)
Time limit per test: 3 seconds
Memory limit per test: 256 megabytes
This is the easy version of the problem. The difference between the versions is that in this version you only need to find the minimum number of operations. You can hack only if you solved all versions of this problem.
Problem Statement
You are given n arrays, each of which has a length of m. Let the j-th element of the i-th array be denoted as a<sub>i,j</sub>. It is guaranteed that all a<sub>i,j</sub> are pairwise distinct.
In one operation, you can do the following:
In other words, you can insert an element at the beginning of any array, after which all elements in this and all following arrays are shifted by one to the right. The last element of the last array is removed.
You are also given a description of the arrays that need to be obtained after all operations. That is, after performing the operations, the j-th element of the i-th array should be equal to b<sub>i,j</sub>. It is guaranteed that all b<sub>i,j</sub> are pairwise distinct.
Determine the minimum number of operations that need to be performed to obtain the desired arrays.
Input
Each test consists of multiple test cases. The first line contains a single integer t (1 ≤ t ≤ 10^4) — the number of test cases. The description of the test cases follows.
For each test case:
It is guaranteed that the sum of n⋅m over all test cases does not exceed 3⋅10^5.
Output
For each test case, output a single integer — the minimum number of operations that need to be performed.
Example
Input:
text4 2 2 2 6 3 4 1 2 7 8 1 5 5 4 1 2 3 5 4 3 2 1 3 3 1 2 3 4 5 6 7 8 9 11 1 2 12 3 4 13 5 6 4 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1 2 3 4 18 5 6 7 19 8 20 9 21 22 10
Output:
text3 5 3 6
Note
In the first test case, the following sequence of 3 operations is suitable:
In the second test case, the desired array can only be achieved in 5 operations.
In the third test case, the following sequence of 3 operations is suitable:
Think of the n × m
table row‑major:
texta11 a12 … a1m a21 a22 … a2m ⋮ an1 an2 … anm
Writing the whole table in one line gives a string
S = s0 s1 … sN‑1
(with N = n m
).
One operation chooses a row i
(so the suffix that starts at position
p = (i‑1)m
) and
p
,So the multiset never grows or shrinks; every operation is just
suffix‑rotate‑by‑1 + “choose what the first element of the suffix becomes”.
Because all numbers are pairwise different, during the whole process every value can be recognised uniquely; only their order matters.
An operation that starts in row i
1 … i‑1
;t
elements of row i
(call the block tail) into the front of row i+1
preserving their order.That means we can finish row 1
, then row 2
, …, row n
one after another and keep the following invariant
before we start row
i
we already have
rows1 … i‑1
exactly equal to their targetsB_1 … B_{i‑1}
.
Denote the row we are just looking at by cur
and the wanted row by goal
.
textcur = c0 c1 … c{m‑1} goal = g0 g1 … g{m‑1}
If we apply t
operations here (pushing the t
needed elements in
reverse order) the row becomes
g0 g1 … g{t‑1} c0 c1 … c{m‑t‑1}
So we may keep the longest prefix of cur
that already equals a suffix of goal
.
Let
textL = longest ℓ (0 ≤ ℓ ≤ m) with c0 … c{ℓ‑1} = g{m‑ℓ} … g{m‑1}
Then the minimal number of pushes in this row is
t = m − L .
After those t
pushes the row is exactly goal
and its tail
tail = c{m‑t} … c{m‑1} (length = t)
is inserted, in that order, in front of the next row.
L
in O(m)Build the array
pattern = cur ⧺ [0] ⧺ goal
(0
is safe as all real numbers are ≥ 1.)
The classical prefix‑function / failure‑function (Knuth–Morris–Pratt)
computed on pattern
gives in its last cell the length of the longest prefix of pattern
that is also its suffix – which is exactly the L
we want.
Because every row is handled once, the total complexity is O(Σ nᵢ mᵢ) ≤ 3·10^5 over the whole test file.
Memory: we just keep the current contents of all rows,
at most N = n m ≤ 3·10^5 integers.
textanswer = 0 rows = original A (vector<vector<int>>) for i = 0 … n‑1 cur = rows[i] // current state of the row goal = B[i] // ---- longest suffix‑prefix length L ---- build T = cur + [0] + goal L = KMP_prefix_function(T).back() t = m – L answer += t // ---- prepare next row ---- if i+1 < n and t > 0 tail = last t elements of cur // c_{m‑t} … c_{m‑1} rows[i+1].insert_front(tail) // prepend tail rows[i+1].resize(m) // drop last t elements // ---- row i is finished ---- rows[i] = goal
Lemma 1 For a fixed row i
the sequence of t = m − L
pushes defined
above is necessary and sufficient to transform its current contents
into goal
.
Proof. Necessity: to change m‑L
wrong leading positions we need at
least that many pushes (each push fixes only the first position).
Sufficiency follows from the construction: after the pushes the row is
exactly goal
. ∎
Lemma 2 The block tail
is inserted in the next row without reordering.
Proof. Every push first removes the last element of the
row (c_{m‑1}, c_{m‑2}, …
) and passes it to the next row,
so the order in which the next row receives them is
c_{m‑1}, c_{m‑2}, …, c_{m‑t}
and after all t
pushes its front is
c_{m‑t} … c_{m‑1}
– precisely tail
. ∎
Theorem The algorithm outputs the minimum possible number of operations.
Proof by induction on rows.
Induction hypothesis: after finishing row i
we used the smallest possible number of operations
to make rows 1 … i
equal their targets.
Base i = 0
: Lemma 1 gives the optimum for the first row.
Induction step:
Assume the hypothesis for i
.
Row i+1
starts with exactly the state produced by Lemma 2.
Any solution must turn that starting state into B_{i+1}
, so by
Lemma 1 it needs at least t_{i+1}
pushes, and our algorithm
uses exactly t_{i+1}
.
Therefore after the step rows 1 … i+1
are optimal too. ∎
cpp#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T--) { int n, m; cin >> n >> m; vector<vector<int>> row(n, vector<int>(m)); for (auto &r : row) for (int &x : r) cin >> x; vector<vector<int>> B(n, vector<int>(m)); for (auto &r : B) for (int &x : r) cin >> x; long long ops = 0; for (int i = 0; i < n; ++i) { auto &cur = row[i]; auto &goal = B[i]; /* build cur + {0} + goal */ vector<int> pat; pat.reserve(2*m + 1); pat.insert(pat.end(), cur.begin(), cur.end()); pat.push_back(0); // separator pat.insert(pat.end(), goal.begin(), goal.end()); /* KMP prefix function */ vector<int> pi(pat.size()); for (size_t j = 1; j < pat.size(); ++j) { int k = pi[j-1]; while (k && pat[j] != pat[k]) k = pi[k-1]; if (pat[j] == pat[k]) ++k; pi[j] = k; } int L = pi.back(); // longest suffix‑prefix int t = m - L; ops += t; if (i + 1 < n && t) { /* take tail and prepend to next row */ auto &nxt = row[i+1]; vector<int> tail(cur.end() - t, cur.end()); vector<int> tmp; tmp.reserve(m); tmp.insert(tmp.end(), tail.begin(), tail.end()); tmp.insert(tmp.end(), nxt.begin(), nxt.end()); nxt.assign(tmp.begin(), tmp.begin() + m); } /* current row is now exactly goal */ cur = goal; } cout << ops << '\n'; } return 0; }
Complexities O(Σ n m)
time, O(n m)
memory – well inside the limits.