zoj 2968 Difference Game (模拟)

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 Gb respectively, 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 p equals 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.

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1967 

经过多次交换,使得ga数组的最小值-gb数组的最大值最小,求这个值。

http://blog.csdn.net/cnh294141800/article/details/22751711时间过得太久我又忘记怎么做了。。。

。。。这一次还是没有做出来。根本原因是没有想到分【答案是正数还是负数】这两种情况。一概而论,所以后来没思路。

这两种情况代表的蕴意分别是:比如现在不是小的都放在b大的都放在a,那么理想的a里面至少有一个实际上放在b里,而这个数肯定是大于a的最小值的。这就是非理想状态。所以正数表示:cost够用,足以变成理想状态;负数表示cost不足以到理想状态,所以是非理想状态。

#include<iostream>  
#include<algorithm>  
#include<string>  
#include<map>//ll dx[4]={0,0,-1,1};ll dy[4]={-1,1,0,0};  
#include<set>//  
#include<vector>  
#include<cmath>  
#include<stack>  
#include<string.h>  
#include<stdlib.h>  
#include<cstdio>   
#define mod 1000000007
#define eps 1e-6
#define ll long long
#define lowbit(x) (x) & (-x) 
using namespace std;
int x[20005];
int y[20005];
struct node{
	int a,b;
}z[40005];
int cmp1(int a,int b){
	return a<b;
}
int cmp2(int a,int b){
	return a>b;
}
int cmp3(node a,node b){
	if(a.a!=b.a)
		return a.a<b.a;
	return a.b<b.b;
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;++i)
			scanf("%d",&x[i]);
		for(int i=1;i<=n;++i)
			scanf("%d",&y[i]);
		if(n==1){  //不能为空,先排除 
			printf("%d\n",x[1]-y[1]);
			continue;
		}
		for(int i=1;i<=n;++i){
			z[i].a=x[i];
			z[i].b=1;
			z[i+n].a=y[i];
			z[i+n].b=2;
		}
		sort(x+1,x+n+1,cmp1);
		sort(y+1,y+n+1,cmp2);
		sort(z+1,z+2*n+1,cmp3);
		int maxx=x[1]-y[1];
		int s1=0,s2=0;
		for(int i=1;i<=2*n-1;++i){ //以i和i+1中间为分割线,左边是最终B的形态,右边是最终a的形态 
			if(z[i].b==1)
				s1++;     //从a送到b的个数 
			s2=n+s1-i;    //从b送到a的个数(原始个数+a送过来的-实际现有的)
			int s=2*min(s1,s2)+abs(s1-s2)*(abs(s1-s2)-1);
			if(s<=m){   //枚举到的情况满足条件 
				maxx=max(maxx,z[i+1].a-z[i].a);
			}
		}
		if(maxx<0){ //小于零代表上面连续的假设不成立,即cost不能达到最优情况 
			int p=m/2+1; //+1是因为从m/2之后的第一个开始算 
			maxx=max(x[p+1]-y[p],x[p]-y[p+1]); 
		}
		printf("%d\n",maxx);
	}
	return 0;
}

下面是两种方法(二分和暴力):
#include<iostream>  
#include<algorithm>  
#include<string>  
#include<map>  
#include<set>  
#include<cmath>  
#include<string.h>  
#include<stdlib.h>  
#include<cstdio>  
#define ll long long  
using namespace std; 
int ga[20001],gb[20001],gc[40003];
int cmp(int a,int b){
	return a>b;
}
int main(){
    int t;  
    scanf("%d",&t); 
    while(t--){  
    	int n,m;
    	scanf("%d%d",&n,&m); 
    	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\n",ga[0]-gb[0]);
    		continue;
    	}
    	sort(ga,ga+n);
    	sort(gb,gb+n,cmp);
    	sort(gc,gc+2*n);
    	int maxn=-1;
    	for(int i=1;i<2*n;++i){
//    		int l=-1,r=n;
//    		while(l+1<r){
//    			int mid=l+(r-l)/2;
//    			if(ga[mid]<gc[i])
//    				l=mid;
//    			else
//    				r=mid; //找到大于等于gc[i]的第一个下标,即为前面有多少个小于gc[i]的 
//    		}
    		int ab=lower_bound(ga,ga+n,gc[i])-ga;
    		int ba=n+ab-i;
    		int u=min(ab,ba),v=abs(ab-ba);
    		int cost=2*u+v*(v-1);
    		if(cost<=m&&gc[i]-gc[i-1]>maxn)
    			maxn=gc[i]-gc[i-1];
    	}
    	if(maxn<=0)
    		printf("%d\n",max(ga[m/2+1]-gb[m/2],ga[m/2]-gb[m/2+1]));
    	else
    		printf("%d\n",maxn);
    }  
    return 0;     
} 
#include<iostream>  
#include<algorithm>  
#include<string>  
#include<map>  
#include<set>  
#include<cmath>  
#include<string.h>  
#include<stdlib.h>  
#include<cstdio>  
#define ll long long  
using namespace std; 
int ga[20001],gb[20001],gc[40003];
int cmp(int a,int b){
	return a>b;
}
int main(){
    int t;  
    scanf("%d",&t); 
    while(t--){  
    	int n,m;
    	scanf("%d%d",&n,&m); 
    	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\n",ga[0]-gb[0]);
    		continue;
    	}
    	sort(ga,ga+n);
    	sort(gb,gb+n,cmp);
    	sort(gc,gc+2*n);
    	int maxn=-1;
    	for(int i=1;i<2*n;++i){
    		int sum1=0,sum2=0;
    		for(int j=0;j<n;++j){
    			if(ga[j]<gc[i])
    				sum1++;
    			else
    				break;
    		}
    		for(int j=0;j<n;++j){
    			if(gb[j]>=gc[i])
    				sum2++;
    			else
    				break;
    		}
    		int ab=sum1;
    		int ba=sum2;
    		int u=min(ab,ba),v=abs(ab-ba);
    		int cost=2*u+v*(v-1);
    		if(cost<=m&&gc[i]-gc[i-1]>maxn)
    			maxn=gc[i]-gc[i-1];
    	}
    	if(maxn>0)
    		printf("%d\n",maxn);
    	else
    		printf("%d\n",max(ga[m/2+1]-gb[m/2],ga[m/2]-gb[m/2+1]));
    }  
    return 0;     
} 


你可能感兴趣的:(zoj 2968 Difference Game (模拟))