[补题记录]AtCoder Beginner Contest 175 D - Moving Piece

AtCoder Beginner Contest 175 D - Moving Piece

题意:

Takahashi will play a game using a piece on an array of squares numbered \(1, 2, \cdots, N\). Square \(i\) has an integer \(C_i\) written on it. Also, he is given a permutation of \(1, 2, \cdots, N\): \(P_1, P_2, \cdots, P_N\).
Now, he will choose one square and place the piece on that square. Then, he will make the following move some number of times between \(1\) and \(K\) (inclusive):

In one move, if the piece is now on Square \(i\) \((1 \leq i \leq N)\), move it to Square \(P_i\). Here, his score increases by \(C_{P_i}\).

Help him by finding the maximum possible score at the end of the game. (The score is \(0\) at the beginning of the game.)

给你两组序列\(N,P\),每次对于\(1\)\(n\)的每一个\(i\)你要把Square \(i\)移到 Square \(P_i\),然后\(i\)的score会增长\(C_{p_i}\),问在这场游戏中能达到的最大score

题解:

首先\(k\leq 10^9\)我们肯定不能模拟,按照样例推导一遍是会发现它是有循环节的,也就是说问题简化为了对于每一个\(i\),有\(a_1,a_1+a_2,\dots,a_1+a_2+a_3+\dots+a_{temp}+a_1+a_2+a_3+\dots\)(一共k项)中出现过的数的最大值

那么我们对于每一个\(i\),把一个循环结存到ve[i]中,ve[i].size()就是循环节的大小

然后记下来\(d=k/len\)最多跑多少个循环节 \(m=k%len\) 最后一个循环节多出来多少个数

如果一个循环节的总和>0,那我们一定是要把所有的循环节跑完的

    now=d*sum[i];
    for(int j=0;j<m;j++) now+=ve[i][j],ans=max(ans,now);

还有就是如果\(m==0\),那\(d--;m=len;\)保留最后一次循环节

如果一个循环节的总和<=0,那我们选了这个循环节还不如不选,只对\(0\)\(d==0?m:ve[i].size()\)取个最优即可

唔 貌似别忘了还要开个long long

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a) & -(a))
#define clean(a, b) memset(a, b, sizeof(a))
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 9;
// typedef pair<int,int>P;

int _;

//========================================================================
ll Pp[maxn],Cc[maxn],mp[5009];
ll a[maxn],sum[maxn];
vector<ll>ve[5009];
//========================================================================
int main()
{
    ll n,k;
    ll x;
    scanf("%lld%lld",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        Pp[i]=a[i];
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&x);
        Cc[i]=x;
    }
    ll ans=-1e18;
    for(ll i=1;i<=n;i++)
    {
        ll now=i;
        clean(mp,0);
        while(1)
        { 
            now=Pp[now];
            if(mp[now]==1) break;
            mp[now]=1;
            sum[i]+=Cc[now];
            ve[i].push_back(Cc[now]);
        }
        int len=ve[i].size();
        ll d=k/len;
        ll m=k%len;
        now=0;
        if(sum[i]>0) 
        {
            if(m==0) 
            {
                now=(d-1)*sum[i];
                m=len;
            }
            else now=d*sum[i];
            for(int j=0;j<m;j++) now+=ve[i][j],ans=max(ans,now);
        }
        else 
        {
            if(d==0)
            {
                for(int j=0;j<m;j++) now+=ve[i][j],ans=max(ans,now);
            }
            else 
            {
                for(int j=0;j<len;j++) now+=ve[i][j],ans=max(ans,now);
            }
        }
    }
    // for(int i=1;i<=n;i++)
    // {
    //     int len=ve[i].size();
    //     for(int j=0;j<len;j++) printf("%lld ",ve[i][j]);
    //     printf("\n");
    // }
    printf("%lld\n",ans);
    return 0;
}
posted @ 2020-08-18 08:41  L·S·D  阅读(188)  评论(0编辑  收藏  举报