CodeM2018美团 初赛A轮 题目二 下棋

CodeM2018美团 初赛A轮 题目二 下棋

[编程|1000分] 下棋
时间限制:C/C++ 1秒,其他语言 2秒
空间限制:C/C++ 262144K,其他语言 524288K
64bit IO Format: %lld
题目描述
有一个1*n的棋盘,上面有若干个棋子,一个格子上可能有多个棋子。
你每次操作是先选择一个棋子,然后选择以下两个操作中的一个:
(1) 若该棋子不在 (1,1),让这个棋子往左走一格,即从 (1,x) 走到 (1,x-1);
(2) 若该棋子不在 (1,n),且这个棋子曾经到达过(1,1),让这个格子往右走一格,即从 (1,x) 走到 (1,x+1)。
给定一开始每个格子上有几个棋子,再给定目标局面每个格子上需要几个棋子,求最少需要多少次操作。

输入描述:
第一行一个正整数n表示棋盘大小。
第二行n个非负整数a_1, a_2, …, a_n 表示一开始 (1,i) 上有几个棋子。
第三行n个非负整数b_1, b_2, …, b_n 表示目标局面里 (1,i) 上有几个棋子。
保证 1 ≤ n ≤ 100,000,

输出描述:
输出一个非负整数,表示最少需要几次操作。
示例1
输入
5
0 0 1 1 0
1 0 0 0 1
输出
9
说明
先把(1,3)上的棋子走到(1,1),花费了2次操作。
然后把(1,4)上的棋子走到(1,1),再往右走到(1,5),花费了3+4=7次操作。
所以一共花了9次操作。
展开答题卡

代码实现:

#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<assert.h>
#include<queue>
#include<string>
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define per(i,j,k) for(int i=(int)j;i>=(int)k;i--)
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
typedef long long LL;
const int N=110000;
int a[N],b[N];
int n;
int main() {
    scanf("%d",&n);
    assert(1<=n&&n<=100000);
    rep(i,1,n)scanf("%d",&a[i]);
    rep(i,1,n)scanf("%d",&b[i]);
    LL suma=0;
    LL sumb=0;
    rep(i,1,n)suma+=a[i];
    rep(i,1,n)sumb+=b[i];
    assert(suma==sumb);
    assert(0<=suma&&suma<=1000000000);

    int aft=0;
    LL ans=0;
    rep(i,1,n)ans+=(a[i]+b[i])*1ll*(i-1);
    per(i,n,1) {
        aft+=a[i];
        ans-=2*(i-1)*1ll*min(b[i],aft);
        aft-=min(b[i],aft);
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lewyu521/article/details/80637436
今日推荐