zoukankan      html  css  js  c++  java
  • bzoj3293 分金币

    题目链接

    problem

    圆桌上坐着n个人,每人有一定数量的金币,金币总数能被n整除。每个人可以给他左右相邻的人一些金币,最终使
    得每个人的金币数目相等。你的任务是求出被转手的金币数量的最小值。

    solution

    肯定会有至少一个相邻位置之间没有进行传递。
    枚举这个位置,假设为k。用x表示每个人最终应有的硬币数量,(S_i)表示前i个人所有的硬币数量和-前i个人应有的硬币数之和。那么在第i个人与第(i-1)个人之间进行传递的硬币数量就是(|S_i-S_k|)。枚举(S_k),统计答案即可。

    code

    /*
    * @Author: wxyww
    * @Date:   2019-12-14 19:29:29
    * @Last Modified time: 2019-12-14 20:23:07
    */
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    const int N = 2000010;
    ll read() {
    	ll x = 0,f = 1;char c = getchar();
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1; c = getchar();
    	}
    	while(c >= '0' && c <= '9') {
    		x = x * 10 + c - '0'; c = getchar();
    	}
    	return x * f;
    }
    ll s[N],a[N];
    int main() {
    	int n = read();
    	ll sum = 0;
    	for(int i = 1;i <= n;++i) a[i] = read(),sum += a[i];
    
    	ll x = sum / n;
    	for(int i = 1;i <= n;++i) a[i] = a[i - 1] + a[i] - x;
    	
    	sort(a + 1,a + n + 1);
    
    	for(int i = n;i >= 1;--i) s[i] = s[i + 1] + a[i];
    	ll now = 0;
    	ll ans = 1e16;
    	for(int i = 1;i <= n;++i) {
    		now += a[i];
    		ans = min(ans,a[i] * i - now + s[i + 1] - a[i] * (n - i));
    	}
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    git 命令行下浏览器tig使用记录
    根据进程名字杀死进程
    centos7 在线安装postgresql9.5
    HttpClient使用代理访问
    nmap查看服务器端口使用情况
    java后台启动jar包
    不同语言,系统通过共享内存方式实现信息交互
    释放 MappedByteBuffer映射的内存
    Java使用ByteBuffer读取大文件
    Java共享内存
  • 原文地址:https://www.cnblogs.com/wxyww/p/bzoj3293.html
Copyright © 2011-2022 走看看