遊戲(game)

遊戲(game)

題目描述

 

這個遊戲是這樣的,你有一個初始序列S ,你每次能夠選擇一段任意長度的連續區間,把他們+1 再膜k,給定目標序列,你須要嘗試用盡可能少的操做次數將初始序列變爲目標序列。做爲一名優秀的OIer,您認爲這個遊戲十分naive,因此您打算擼一個遊戲腳原本取到最優解。php

 

輸入

 

第一行一個T 表示數據組數。ios

對於每組數據,第一行兩個整數表示序列長度和模數。spa

接下來兩行分別包含n 個整數,表示初始序列和目標序列。code

 

輸出

 

對於每組數據,輸出一行一個整數表示最少操做次數。blog

 

樣例輸入

<span style="color:#333333"><span style="color:#333333">1
6 4
1 1 3 2 0 2
2 0 2 3 2 0</span></span>

樣例輸出

<span style="color:#333333"><span style="color:#333333">4</span></span>

提示

 

樣例解釋遊戲

四次操做的一種方式爲:(1,6)(2,3)(2,3)(5,6)ip

數據範圍ci

1≤T≤51≤T≤5get

對於10% 的數據知足n≤1n≤1string

對於30% 的數據知足n≤10n≤10

對於50% 的數據知足n≤100n≤100

對於70% 的數據知足n≤5000n≤5000

對於100% 的數據知足1≤n≤100000,1≤k≤100,0≤x1≤n≤100000,1≤k≤100,0≤x(序列中的任一數)<k<k

 

來源

noip2018模擬-北京十一


solution

首先咱們能夠求出每個位置須要操做幾回。

設爲a[i].記c[i]=a[i]-a[i-1]

ans=\sum max(c[i],0)

咱們能夠把a[i]的連續一段加上k

至關於把位置+k 另外一個位置-k

咱們應該要把一個大於零的減掉k,小於零的加k使答案更優

因而用一個桶存下小於零的,每次取儘可能小便可

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 100005
using namespace std;
int T,n,k,a[maxn],t,f[maxn],g[maxn],c[maxn],tax[202],ans;
int main()
{
    cin>>T;
    while(T--){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n;i++){
            scanf("%d",&t);
            int ne=t-a[i];ne=(ne+k)%k;
            a[i]=ne;
        }
        a[0]=0;
        for(int i=1;i<=n;i++)c[i]=a[i]-a[i-1];ans=0;
        memset(tax,0,sizeof tax);
        for(int i=1;i<=n;i++){
            if(c[i]<0)tax[c[i]+k]++;
            else {
                bool fl=0;
                for(int j=0;j<c[i];j++)if(tax[j]){
                    tax[j]--;tax[c[i]]++;
                    ans=ans+j;
                    fl=1;break;
                }
                if(!fl)ans=ans+c[i];
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
相關文章
相關標籤/搜索