E. Permutation Sorting

发布时间 2023-12-01 18:13:11作者: onlyblues

E. Permutation Sorting

You are given a permutation$^\dagger$ $a$ of size $n$. We call an index $i$ good if $a_i=i$ is satisfied. After each second, we rotate all indices that are not good to the right by one position. Formally,

  • Let $s_1,s_2,\ldots,s_k$ be the indices of $a$ that are not good in increasing order. That is, $s_j < s_{j+1}$ and if index $i$ is not good, then there exists $j$ such that $s_j=i$.
  • For each $i$ from $1$ to $k$, we assign $a_{s_{(i \% k+1)}} := a_{s_i}$ all at once.

For each $i$ from $1$ to $n$, find the first time that index $i$ becomes good.

$^\dagger$ A permutation is an array consisting of $n$ distinct integers from $1$ to $n$ in arbitrary order. For example, $[2,3,1,5,4]$ is a permutation, but $[1,2,2]$ is not a permutation ($2$ appears twice in the array) and $[1,3,4]$ is also not a permutation ($n=3$ but there is $4$ in the array).

Input

Each test contains multiple test cases. The first line contains the number of test cases $t$ ($1 \le t \le 10^4$). The description of the test cases follows.

The first line of each test case contains a single integer $n$ ($1 \le n \le 10^6$) — the size of permutation $a$.

The second line of each test case contains $n$ integers $a_1, a_2, \ldots, a_n$ ($1 \le a_i \le n$) — the elements of permutation $a$.

It is guaranteed that the sum of $n$ over all test cases does not exceed $10^6$.

Output

For each test case, output a single line containing $n$ integers where the $i$-th integer represents the first time that index $i$ becomes good.

Example

input

2
5
3 2 4 1 5
6
2 1 4 6 5 3

output

1 0 1 1 0 
2 1 2 1 0 1 

Note

In the first test case, $2$ and $5$ are already in the correct position so indices $2$ and $5$ become good at $0$ second. After $1$ second, a cyclic shift will be done with $s=[1, 3, 4]$, resulting in array $a=[1, 2, 3, 4, 5]$. Notice that indices $1$, $3$ and $4$ become good at $1$ second.

In the second test case, $5$ is already in the correct position, so index $5$ becomes good at $0$ second. After $1$ second, a cyclic shift will be done with $s=[1, 2, 3, 4, 6]$, resulting in array $a=[3, 2, 1, 4, 5, 6]$. Notice that indices $2$, $4$ and $6$ become good at $1$ second. After $2$ seconds, a cyclic shift will be done with $s=[1, 3]$, resulting in array $a=[1, 2, 3, 4, 5, 6]$. Notice that indices $1$ and $3$ become good at $2$ second.

 

解题思路

  为了方便将数组 $a$ 的每个元素减 $1$。定义 $h_i$ 表示将元素 $a_i$ 从下标 $i$ 移到下标 $a_i$ 所需要的时间,有 $h_i = (a_i - i) \bmod n$。同时破环成链,把数组 $h$ 拷贝一份接到后面,即对于 $i \in [n, 2n - 1]$,有 $h_i = h_{i - n}$。

  考虑计算下标为 $a_i$ 的答案,首先需要将 $a_i$ 向右移动 $h_i$ 个时间,假设在这个过程中存在元素 $a_j,$ 满足 $j \in [i+1, i+h_i]$ 且 $j + h_j \in [i + 1, i + h_i]$,即在 $a_i$ 移动的过程中这些元素移动到其对应的下标,那么 $a_i$ 就要跳过这些元素。假设有 $c$ 个这样的元素,那么实际上 $a_i$ 只用移动 $h_i - c$ 个时间。

  因此对于每个 $a_i$,只需统计出有多少个元素 $a_j$ 满足 $\displaylines{\begin{cases} i+1 \leq j \leq i+h_i \\ i+1 \leq j+h_j \leq i+h_i \end{cases}}$。可以看作是一个二维数点问题,对于每个下标 $j \in [0,n-1]$,将 $(j, h_j)$ 看作是一个点,那么就相当于询问左下角为 $(i+1, i+1)$ 右上角为 $(i+h_i, i+h_i)$ 的矩形内有多少点。

  AC 代码如下,时间复杂度为 $O(n \log{n})$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1e6 + 10, M = N * 2;

int n;
int a[N], h[M];
int tr[M];
struct Node {
    int x, y, c, idx;
}p[N * 4];
int ans[N];

int lowbit(int x) {
    return x & -x;
}

void add(int x, int c) {
    for (int i = x; i <= n << 1; i += lowbit(i)) {
        tr[i] += c;
    }
}

int query(int x) {
    int ret = 0;
    for (int i = x; i; i -= lowbit(i)) {
        ret += tr[i];
    }
    return ret;
}

void solve() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", a + i);
        a[i]--;
        h[i] = h[i + n] = (a[i] - i + n) % n;
    }
    for (int i = 0, j = 0; i < n; i++) {
        int x1 = i + 1, y1 = i + 1, x2 = i + h[i], y2 = i + h[i];
        p[j++] = {x2, y2, 1, i};
        p[j++] = {x1 - 1, y1 - 1, 1, i};
        p[j++] = {x1 - 1, y2, -1, i};
        p[j++] = {x2, y1 - 1, -1, i};
    }
    sort(p, p + n * 4, [&](Node &a, Node &b) {
        return a.x < b.x;
    });
    for (int i = 0; i < n; i++) {
        ans[a[i] % n] = h[i];
    }
    memset(tr, 0, n + 10 << 3);
    for (int i = 0, j = 0; i < n << 2; i++) {
        while (j < n << 1 && j <= p[i].x) {
            add(j + h[j] + 1, 1);    // 由于j+h[j]可能为0,因此加一个偏移量
            j++;
        }
        ans[a[p[i].idx] % n] -= p[i].c * query(p[i].y + 1);    // 同理加一个偏移量
    }
    for (int i = 0; i < n; i++) {
        printf("%d ", ans[i]);
    }
    printf("\n");
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  CodeTON Round 7 (Div. 1 + Div. 2, Rated, Prizes!) Editorial:https://codeforces.com/blog/entry/122172