题干:
Now you are going to play an interesting game. In this game, you are given two groups of distinct integers and C coins. The two groups, named Ga and Gbrespectively, are not empty and contain the same number of integers at first. Each time you can move one integer in one group to the other group. But a move that makes a group empty is considered as invalid. Each move will cost you p coins, and pequals the difference of the size between the two group (take the absolute value. e.g. moving a number from the group of size 4 to the group of size 6 will cost you |4 - 6| = 2 coins, and moving a number between two group with same size will not cost any coins). You can do as many moves as you wish, so long as the total cost does not exceed C.
Let M be the minimum integer in Ga, and N be the maximum integer in Gb. The purpose of this game is to produce a maximum (M - N).
Input
Standard input will contain multiple test cases. The first line of the input is a single integer T (1 <= T <= 60) which is the number of test cases. And it will be followed by T consecutive test cases.
Each case begin with two integers S (1 <= S <= 20000, indicating the size of Ga and Gb at first) and C (0 <= C <= 1000000). Two lines of S integers follow, representing the numbers in Ga and Gb respectively. All these integers are distinct and are between 1 and 50000, both inclusive.
Output
Results should be directed to standard output. The output of each test case should be a single integer in one line, which is the maximum possible value for M - N after some moves.
Sample Input
2
1 10
10
12
2 10
1 2
3 4
Sample Output
-2
1
Hint
For Sample 1, two groups are of size 1, so no moves can be done because any moving will make Ga or Gb empty, which is not valid. So M = 10, N = 12, M - N = -2.
For Sample 2, one valid steps of moves is:
Move 1 in Ga to Gb, cost 0 coins.
Move 3 in Gb to Ga, cost 2 coins.
Move 4 in Gb to Ga, cost 0 coins.
Then Ga contains 2 3 4, Gb contains 1, M = 2, N = 1, M - N = 1. This is the maximum possible value.
题目大意:
有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堆,当然是交替移。
但是做完题后,有个疑问,如果A中的值很大,B中的值很小,那是不是选择不移动,会得到更优答案?
答案是否定的,(也就是说首先拿到这题第一颗定心丸就是:交换总比不交换要好,也就是如果还有钱就一定要去交换),因为他是要 ,所以你把Bmax或者Amin换过去,会使得Amin变大,Bmax变小,所以对两个参数都有利,那么根据贪心原则,何乐而不为?
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 4e5 + 5;
int n;
struct Node {ll val;int id;bool operator<(const Node & b) {return val < b.val;}
} g[MAX],ga[MAX],gb[MAX];
int suma[MAX],Sumb[MAX];
int main() {int t;cin>>t;int s,c;while(t--) {memset(g,0,sizeof g);memset(ga,0,sizeof ga);memset(gb,0,sizeof gb);memset(suma,0,sizeof suma);memset(Sumb,0,sizeof Sumb);scanf("%d%d",&s,&c);ll ans = -1;for(int i = 1; i<=s; i++) scanf("%lld",&ga[i].val),ga[i].id = 1;for(int i = 1; i<=s; i++) scanf("%lld",&gb[i].val),gb[i].id = 2;for(int i = 1; i<=2*s; i++) {if(i<=s) g[i] = ga[i];else g[i] = gb[i-s];}sort(ga+1,ga+s+1);sort(gb+1,gb+s+1);sort(g+1,g+2*s+1);for(int i = 1; i<=2*s; i++) {suma[i] = suma[i-1];if(g[i].id == 1) suma[i]++;}for(int i = 2*s; i>=1; i--) {Sumb[i] = Sumb[i+1];if(g[i].id == 2) Sumb[i]++;}if(s == 1) {printf("%d\n",ga[1].val-gb[1].val);continue;}for(int i = 1; i<2*s; i++) {//在i这个地方断开int numa = suma[i];int numb = Sumb[i+1];int ci = min(numa,numb);ll tmp;//花钱数if(ci == numa) {ll sheng = numb - numa;tmp = ci*2 + sheng*(sheng-1);} else {ll sheng = numa - numb;tmp = ci*2 + sheng*(sheng-1);}if(tmp <= c) {ans = max(ans,g[i+1].val-g[i].val);}}if(ans==-1) {int ci = c/2+1;ans=max(ga[ci].val-gb[s-ci].val,ga[ci+1].val-gb[s-(ci-1)].val);}printf("%lld\n",ans);}return 0 ;
}