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;     
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值