首页 > 其他分享 >E. Permutation Sorting

E. Permutation Sorting

时间:2023-12-01 18:14:20浏览次数:33  
标签:good int permutation le second Sorting Permutation test

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

标签:good,int,permutation,le,second,Sorting,Permutation,test
From: https://www.cnblogs.com/onlyblues/p/17870634.html

相关文章

  • [Codeforces] CF1858C Yet Another Permutation Problem
    YetAnotherPermutationProblem-洛谷这题本来很简单,思路我也想到了,但是代码一直没写对,思路也一直换来换去(悲然而发现最开始的思路是对的题意Alex收到了一个名为"GCD排列"的游戏作为生日礼物。这个游戏的每一轮进行如下操作:首先,Alex选择一个整数序列\(a_1,a_2,…,a_......
  • DPT Permutation
    题意给定\(S\in['>','<']\)。表示排列\(P\)两点之间的大小关系。求排列\(P\)的方案数。Sol排列方案,考虑\(f_{i,j}\)表示第\(i\)位的数在排列中排名为\(j\)的方案数。当\(S_i='>'\),\(f_{i,j}=\sum_{k=1}^{j-1}f_{i-1,k}\)。当\(S......
  • CF1858C Yet Another Permutation Problem
    CF1858CYetAnotherPermutationProblemYetAnotherPermutationProblem-洛谷这题本来很简单,思路我也想到了,但是代码一直没写对,思路也一直换来换去(悲然而发现最开始的思路是对的题意Alex收到了一个名为"GCD排列"的游戏作为生日礼物。这个游戏的每一轮进行如下操作:......
  • 题解 P7972【[KSN2021] Self Permutation】
    怎么其他两篇题解都是\(O(n\logn)\)的,来发一个\(O(n)\)做法,当考前复习了。对原序列建出小根笛卡尔树,节点编号与原序列中的下标相同。记\(T_u\)表示以\(u\)为根的子树,\(lc(u),rc(u)\)分别表示\(u\)的左儿子和右儿子。设\(f_u\)表示删除若干\(T_u\)中的点(可以不删......
  • CF1542E2 Abnormal Permutation Pairs (hard version) 题解
    怎么会有这么离谱的题目啊。【模板】前缀和优化dp。思路考虑一个基本的东西。由于要求字典序的限制。我们可以枚举最长公共前缀计算。考虑如何求长度为\(i\)的排列有\(j\)个逆序对的数量。设\(dp_{i,j}\)。\[dp_{i,j}=\sum_{k=0}^{i-1}dp_{i-1,j-k}\]就是枚举新的......
  • [题解] CF1156E Special Segments of Permutation
    SpecialSegmentsofPermutation给你一个排列\(p\),求有多少个区间\([l,r]\)满足\(p_l+p_r=\max_{i\in[l,r]}p_i\)。\(n\le2\times10^5\)。按最大值分治,记当前的分治中心为\(mid\),分治区间为\([l,r]\)。然后需要计算跨分治中心的贡献。如果\(mid-l......
  • SP15637 GNYR04H - Mr Youngs Picture Permutations(线性 dp)
    题目求方案数,考虑dp——状态设计和边界——题目告诉了一个很显然的性质:每一排从左至右保证高度单调递减每一列从后往前保证高度单调递减那么可以发现,对于每一行,每一列,一定是按高度顺序插入,并且是连续插入,因为如果不连续,就无法保证单调递减的性质同时,它给出了另一个性......
  • CF213E Two Permutations
    CF213ETwoPermutations题解下文的\(a+x\)表示\(a_1+x,a_2+x,...a_n+x\)这个序列。发现\(n,m\)不大,所以可以枚举\(x\),然后快速判断是否合法。考虑如何快速判断一个\(x\)是否合法。注意到\(a,b\)都是排列。\(a_1+x,a_2+x,...a_n+x\)的数在\([1+x,n+x]\)范围内......
  • 「CF715E」Complete the Permutations
    \(\text{「CF715E」CompletethePermutations}\)\(\text{Link}\)\(\text{Describe}\)给定长为\(n\)的且部分确定的置换\(p,q\)。定义\(p,q\)距离为通过交换\(p\)任意两项变为\(q\)的最小步数,对于\(0\lek\len-1\)求通过补全\(p,q\)使得\(p,q\)距离为\(k\)的......
  • UVA1485 Permutation Counting
    传送门description一个长度为\(n\)的排列\(a\),其权值为满足\(a_i>i\)的位置的数量。求权值恰为\(k\)的长度为\(n\)的排列的方案数。\(n,k\leq1000\)solution设\(f_{i,j}\)表示考虑前\(i\)个数,钦定\(j\)个满足\(a_i>i\),这\(j\)个数排列的方案数。有转移......