codeforces - 1249B2 Books Exchange (hard version)

https://vjudge.net/problem/CodeForces-1249B2

题目描述:

The only difference between easy and hard versions is constraints.

There are nn kids, each of them is reading a unique book. At the end of any day, the ii-th kid will give his book to the pipi-th kid (in case of i=pii=pi the kid will give his book to himself). It is guaranteed that all values of pipi are distinct integers from 11 to nn (i.e. pp is a permutation). The sequence pp doesn‘t change from day to day, it is fixed.

For example, if n=6n=6 and p=[4,6,1,3,5,2]p=[4,6,1,3,5,2] then at the end of the first day the book of the 11-st kid will belong to the 44-th kid, the 22-nd kid will belong to the 66-th kid and so on. At the end of the second day the book of the 11-st kid will belong to the 33-th kid, the 22-nd kid will belong to the 22-th kid and so on.

Your task is to determine the number of the day the book of the ii-th child is returned back to him for the first time for every ii from 11 to nn.

Consider the following example: p=[5,1,2,4,3]p=[5,1,2,4,3]. The book of the 11-st kid will be passed to the following kids:

  • after the 11-st day it will belong to the 55-th kid,
  • after the 22-nd day it will belong to the 33-rd kid,
  • after the 33-rd day it will belong to the 22-nd kid,
  • after the 44-th day it will belong to the 11-st kid.

So after the fourth day, the book of the first kid will return to its owner. The book of the fourth kid will return to him for the first time after exactly one day.

You have to answer qq independent queries.

Input

The first line of the input contains one integer qq (1≤q≤10001≤q≤1000) — the number of queries. Then qq queries follow.

The first line of the query contains one integer nn (1≤n≤2⋅1051≤n≤2⋅105) — the number of kids in the query. The second line of the query contains nn integers p1,p2,…,pnp1,p2,…,pn (1≤pi≤n1≤pi≤n, all pipi are distinct, i.e. pp is a permutation), where pipi is the kid which will get the book of the ii-th kid.

It is guaranteed that ∑n≤2⋅105∑n≤2⋅105 (sum of nn over all queries does not exceed 2⋅1052⋅105).

Output

For each query, print the answer on it: nn integers a1,a2,…,ana1,a2,…,an, where aiai is the number of the day the book of the ii-th child is returned back to him for the first time in this query.

Example

Input

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

Output

1 1 1 1 1
3 3 3
2 3 3 2 1 3
1
2 2 2 2
4 4 4 1 4   题意就是从一列数的第i个数开始,然后移动到第ai个数,这样不断移动下去回到第i个数需要经过多少次。显然从i->i中的所有数可以组成一个圆环,所有圆环中的元素需要移动的次数是一样的,所以对于每一个没有搜索过的数来说,在搜索过程中出现的数字需要移动的次数是一样的,我们把这些结果记录下来,避免重复搜索,就可以做到O(n)的复杂度了
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define endl ‘\n‘
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define mst(a) memset(a, 0, sizeof(a))
#define IOS ios::sync_with_stdio(false)
#define _test printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n")
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const double pi = acos(-1.0);
const double eps = 1e-7;
const ll MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int _NAN = -0x3f3f3f3f;
const int NIL = -1;
const int maxn = 2e5+10;
int arr[maxn], ans[maxn], cnt;
void solve(int x, int pos) {
    if (x != arr[pos]) {
        ++cnt;
        solve(x, arr[pos]);
    }
    ans[pos] = cnt;
}
int main(void) {
    int t;
    scanf("%d", &t);
    while(t--) {
        int n;
        scanf("%d", &n);
        for (int i = 1; i<=n; ++i)
            scanf("%d", &arr[i]);
        for (int i = 1; i<=n; ++i)
            if (!ans[i]) {
                cnt = 1;
                solve(i, i);
            }
        for (int i = 1; i<=n; ++i)
            printf(i == n ? "%d\n" : "%d ", ans[i]);
        mst(ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/shuitiangong/p/12273942.html

时间: 2024-10-02 23:38:49

codeforces - 1249B2 Books Exchange (hard version)的相关文章

CodeForces 1118F2. Tree Cutting (Hard Version)

题目简述:给定$n \leq 3 \times 10^5$个节点的树,其中一部分节点被染色,一共有$k$种不同的颜色.求将树划分成 $k$ 个不相交的部分的方案数,使得每个部分中除了未染色的节点以外的所有节点颜色相同,答案模$998244353$(质数). 解:code Step 1. 缩点 相关题目:CodeForces 76F. Tourist 观察:为使相同颜色的节点处在同一个子树中,则包含这些节点的最小子树的所有节点必然会被划分在同一部分. 因此,在随意选择一个节点作为树的根节点后,每种

codeforces#1290E2 - Rotate Columns (hard version)(子集dp)

题目链接: https://codeforces.com/contest/1209/problem/E2 题意: 给出$n$行和$m$列 每次操作循环挪动某列一次 可以执行无数次这样的操作 让每行最大值的累加和最大 数据范围: $1\leq n \leq 12$ $1\leq m \leq 20000$ 分析: 定义$dp[i][j]$,考虑前$i$列,选择状态为$j$的最大值 $ans=dp[m][(1<<n)-1]$ $dp[i][j]$可以由$dp[i-1][k]$转移,$k$是$j$的

Codeforces--Books Exchange (hard version)

题目链接http://codeforces.com/contest/1249/problem/B2 .并查集思想,将数分成多个集合,每个集合的大小就是一轮的所需天数. Map[i]存储数据. flag[i]来表示第i个数是否被访问过. mm[i]记录第i个集合所对应的集合大小,索引i为第i个集合的根对应的值. getParent方法利用递归的思想更新每个节点的上继,直接指向当前集合的根. 由于访问过的集合不再进行访问,因此,分析时间复杂度,准确是O(CN),C为一个常数.在这里需要注意的是,mm

CodeForces 279B Books (滑动窗口)

题意:给定n本书的阅读时间,然后你从第 i 本开始阅读,问你最多能看多少本书在给定时间内. 析:就是一个滑动窗口的水题. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream>

Codeforces 279B Books

#include<bits/stdc++.h> using namespace std; int a[100020]; int main() { int n,t; scanf("%d%d",&n,&t); int sum=0,k=1,Max=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); sum+=a[i]; while(sum>t) { sum-=a[k]; k++; }

Codeforces 1296E2 - String Coloring (hard version)

题目大意: 给定一段长度为n的字符串s 你需要给每个字符进行涂色,然后相邻的不同色的字符可以进行交换 需要保证涂色后能通过相邻交换把这个字符串按照字典序排序(a~z) 你可以使用无限种颜色,但是要保证用到的颜色种类最少 从1开始对颜色进行编号,先输出最少使用的颜色种类,再给出涂色方案 解题思路 1: 可以引入一个 r 数组,开26个空间代表26种字母 这个数组 r[i] 的值代表 第 i 个字母在前面涂的颜色最大编号是多少,0表示没出现过 遍历这个字符串,再从当前字母后一个位置开始往后再遍历这个

Codeforces 1326D2 - Prefix-Suffix Palindrome (Hard version)

题目大意 T组数据,每组给定一个字符串 s 求一个最长的字符串 t ,满足: t 是一个回文串 t = a+b ,a是字符串s的前缀,b是字符串s的后缀,'+' 为拼接两字符串,ab可能为空串 数据范围 数据组数不超过 1e5 字符串的总共长度不超过 1e6 解题思路 (标准做法应该是哈希) 因为对于任意的字符串T,设R(T)为T的倒置 则 T+回文串+R(T) 仍然是一个回文串 可以直接双指针在s里找出最长的 T和R(T) while(L<R&&s[L]==s[R]) L++,R-

Codeforces Round #595 (Div. 3)

比赛链接:传送门 Codeforces1249A. Yet Another Dividing into Teams(水题) 代码: #include <bits/stdc++.h> #define N 105 using namespace std; int a[N]; int main() { int q; cin >> q; while (q--) { int n; cin >> n; for (int i = 1; i <= n; i++) { cin &g

cf 595 补题

1.B2   Books Exchange (hard version) 题意:有n(1~n)个孩子看书,定义一个数组,记录了每个孩子看完??,把书给的下一个人 T个样例,输出孩子重新拿到自己的书需要的传递次数 思路:easy  : i=a[ i ] ;直到 i ==本身,记录次数     hard :   递归找环 ,运用递归,减少遍历次数,就是说一次递归把环上的所有点的次数全部找到. #include<bits/stdc++.h> using namespace std; const in