ZOJ 2968 Difference Game 【贪心 + 二分】

题意:
有Ga、Gb两堆数字,初始时两堆数量相同。从一一堆中移一一个数字到另一一堆的花费定义为两堆之间数
量差的绝对值,初始时共有钱C。求移动后Ga的最小小值减Gb的最大大值可能的最大大值。
思路:
假如有足足够钱移动,那么Ga的最大大值和Gb的最小小值应该是两堆合并后排序中相邻的两数。那么我们
就枚举这个数。枚举的时候我们需要确定形成这个情况(大大的都在Ga堆,小小的都在Gb堆)的最少花
费,这个花费可以这样解决,假设Ga中向Gb中需要移入入ab个数,Gb需要向Ga移入入ba个数,首首先当
然是Ga移一一个给Gb,然后Gb移一一个给Ga,这样直到某一一堆需要移出都移出停止止,此时的花费就是
2*min(ab,ba)。接着就是其中一一堆一一直移给另一一堆,每移一一次费用用会增2,所以此时的花费为
|ab-ba|*(|ab-ba|-1)。总花费就为2*min(ab,ba) + |ab - ba| *(|ab -ba|- 1)。
当然可能没有足足够钱移动,Ga堆的最小小值永远小小于Gb堆的最大大值,这样我们当然要把Ga堆前C/2
(C/2+1)小小的移到Gb堆,Gb堆前C/2+1(C/2)的移到Ga堆,当然是交替移。

By @sake

  

Source Code:

//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cmath>
#include <stack>
#include <string>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <vector>
#include <algorithm>
#define Max(a,b) (((a) > (b)) ? (a) : (b))
#define Min(a,b) (((a) < (b)) ? (a) : (b))
#define Abs(x) (((x) > 0) ? (x) : (-(x)))
#define MOD 1000000007
#define pi acos(-1.0)

using namespace std;


int ga[20010], gb[20010], gc[50000];
bool cmp(const int & a, const int &b){
    return a > b;
}
//二分查找,关键字key,右边界n,左边界默认-1
int b_search(int key, int n){
    int l = -1, r = n, m;
    while (l+1 < r) {
        m = (l+r)/2;
        if (ga[m] < key) {
            l = m;
        } else {
            r = m;
        }
    }
    return r;
}
int main(){
    int t;
    scanf("%d", &t);while (t--) {
        int n, cost;
        scanf("%d%d", &n, &cost);
        for (int i = 0; i < n; i ++) {
            scanf("%d", &ga[i]);
            gc[i] = ga[i];
        }
        for (int i = 0; i < n; i ++) {
            scanf("%d", &gb[i]);
            gc[i+n] = gb[i];
        }
        if (n == 1) {
            printf("%d
", ga[0] - gb[0]);
            continue;
        }
        sort(ga, ga+n);
        sort(gc, gc+2*n);
        sort(gb, gb+n, cmp);
        int maxn = -50000;
        for (int i = 1; i < 2*n; i ++) {
            int ab = b_search(gc[i], n);
            int ba = (2*n - i) - (n - ab);
            int mab = min(ab, ba);
            int fab = abs(ab-ba);
            int c = 2*mab + (fab-1)*fab;
            if (c <= cost) {
                maxn = max(maxn, gc[i]-gc[i-1]);
            }
        }
        if (maxn > 0) {
            printf("%d
", maxn);
        } else {
            int ans = max(ga[cost/2]-gb[cost/2+1], ga[cost/2+1]-gb[cost/2]);
            printf("%d
", ans);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wushuaiyi/p/4393732.html