A - Books Exchange (hard version)(传递书籍一个轮回所需天数)

The only difference between easy and hard versions is constraints.

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

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

Your task is to determine the number of the day the book of the i-th child is returned back to him for the first time for every i from 1 to n.

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

after the 1-st day it will belong to the 5-th kid,
after the 2-nd day it will belong to the 3-rd kid,
after the 3-rd day it will belong to the 2-nd kid,
after the 4-th day it will belong to the 1-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 q independent queries.

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

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

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

Output
For each query, print the answer on it: n integers a1,a2,…,an, where ai is the number of the day the book of the i-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
思路:传递书本的过程中,会经过若干个同学。其中每一个同学的轮回所需天数都是相同的,所以计算一个人的答案的时候,用数组把所经过的每个人的答案都记录下来,避免重复经过大量计算导致tle。

#include <bits/stdc++.h>
using namespace std;
int dis[4][2]={0,1,0,-1,1,0,-1,0},a[105][105];
int n,m,sx,sy,ex,ey,ans;
bool vis[105][105];
struct node
{
    int x,y,step,time;
};
queue<node> q;

void bfs(int x,int y)
{
    q.push(node{x,y,0,6});
    while(!q.empty())
    {
        node tmp=q.front();
        q.pop();
        int dx=tmp.x;
        int dy=tmp.y;
        if(dx==ex && dy==ey) {ans=tmp.step;return;}
        if(tmp.time<=1) continue;
        for(int i=0;i<4;i++)
        {
            int tx=dx+dis[i][0];
            int ty=dy+dis[i][1];
            if(tx>=1 && tx<=n && ty>=1 && ty<=m && a[tx][ty]!=0 && !vis[tx][ty])
            {
                if(a[tx][ty]==4)
                {
                    vis[tx][ty]=1;
                    q.push(node{tx,ty,tmp.step+1,6});
                }
                else q.push(node{tx,ty,tmp.step+1,tmp.time-1});
            }
        }

    }
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ans=-1;
        cin>>n>>m;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                cin>>a[i][j];
                if(a[i][j]==2) sx=i,sy=j;
                if(a[i][j]==3) ex=i,ey=j;
            }
        bfs(sx,sy);
        cout<<ans<<endl;
        while(!q.empty()) q.pop();
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个基于GroupLens的Book-Crossing数据集的Python书籍推荐系统的示例代码: ```python import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.metrics.pairwise import cosine_similarity # 加载数据集 ratings = pd.read_csv('BX-Book-Ratings.csv', delimiter=';', error_bad_lines=False, encoding="latin-1") books = pd.read_csv('BX-Books.csv', delimiter=';', error_bad_lines=False, encoding="latin-1") users = pd.read_csv('BX-Users.csv', delimiter=';', error_bad_lines=False, encoding="latin-1") # 过滤掉评分次数少于50次的书籍 book_ratings_count = pd.DataFrame(ratings.groupby('ISBN')['Book-Rating'].count()) book_ratings_count = book_ratings_count[book_ratings_count['Book-Rating'] >= 50] book_ratings_count.reset_index(inplace=True) # 合并数据集 ratings = pd.merge(ratings, book_ratings_count, on='ISBN', how='inner') ratings.drop('Book-Rating_y', axis=1, inplace=True) ratings.rename(columns={'Book-Rating_x': 'Book-Rating'}, inplace=True) # 过滤掉评分次数少于50次的用户 user_ratings_count = pd.DataFrame(ratings.groupby('User-ID')['Book-Rating'].count()) user_ratings_count = user_ratings_count[user_ratings_count['Book-Rating'] >= 50] user_ratings_count.reset_index(inplace=True) # 合并数据集 ratings = pd.merge(ratings, user_ratings_count, on='User-ID', how='inner') ratings.drop('Book-Rating_y', axis=1, inplace=True) ratings.rename(columns={'Book-Rating_x': 'Book-Rating'}, inplace=True) # 构建评分矩阵 ratings_matrix = ratings.pivot_table(index='User-ID', columns='ISBN', values='Book-Rating') # 填充缺失值 ratings_matrix.fillna(0, inplace=True) # 计算相似度矩阵 cosine_sim = cosine_similarity(ratings_matrix) # 定义函数:获取相似的书籍 def get_similar_books(book_title, cosine_sim=cosine_sim): idx = books[books['Book-Title'] == book_title].index[0] sim_scores = list(enumerate(cosine_sim[idx])) sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True) sim_scores = sim_scores[1:11] book_indices = [i[0] for i in sim_scores] return books['Book-Title'].iloc[book_indices] # 测试 book_title = 'The Da Vinci Code' print('对于书籍:', book_title, '的推荐如下:') print(get_similar_books(book_title)) ``` 这个示例代码使用了基于内容的推荐算法,通过计算书籍的相似度来进行推荐。具体实现中,首先加载了Book-Crossing数据集,并过滤掉了评分次数过少的书籍和用户。然后,构建了评分矩阵,并计算了相似度矩阵。最后,定义了一个函数,通过输入书籍名称,返回相似度最高的10本书籍。 需要注意的是,这个示例代码只是一个基础的框架,实际使用时需要根据具体业务需求进行调整和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值