Codeforces Round #658 (Div. 2)E Mastermind(补题)

Codeforces Round #658 (Div. 2)E Mastermind(补题)_第1张图片

Codeforces Round #658 (Div. 2)E Mastermind(补题)_第2张图片

Codeforces Round #658 (Div. 2)E Mastermind(补题)_第3张图片

Codeforces Round #658 (Div. 2)E Mastermind(补题)_第4张图片

题意:两个数组,长度一样。他们中有x个是一模一样,y个经过换序可以一样。给出长度n和x,y,再给出其中一个数组,问能不能有另一个数组符合要求。有就输出YES并打印这个数组,否则输出NO。

分析:以后我不做2500的题了,对自己太自信了。没有金刚钻,不去试这些玩意了。

首先对数组按数值从小到大排序,然后计算相同量,每个数和前一个数相同,相同量就是前一个数+1.然后按照相同量从大到小排序,把x的指标优先配发给相同量高的数。然后从没配发的(假设长度为len)开始按数值从小到大排序,配发值为a[i+len/2].val注意如果不分的话要加上已配发的数num再减去n(相当于没有配发的数绕成环)

令tmp=n-y;然后一一甄别这些数,要是配发的值和自己数值相等了,那就让他为额外的数(根据定义额外的数一定存在)tmp--。当tmp仍然存在的时候就选一些不被额外数替代的数变成这些值就可以了。

判no的条件是n-y+n-num<2*a[i].sam,因为这个情况下就算你把所有的值全部相等加上额外数,也抵消不掉相同的这么多。

一开始我想的是能不能先去x再去n-p,wa了不知道多少次。

代码:

#include
using namespace std;
const int N=100005;
struct shu
{
	int val;//代表值
	int sam;//代表相同量
	int pos;//代表位置
	int cor;//代表对应值应该是多少 
}a[N];
int ji[N];//记录有哪些数已经被用到了
int unuse[N];//还有这些数没有被用过 
int cmp1(shu x1,shu x2)
{
	return x1.valx2.sam;
}
int cmp3(shu x1,shu x2)
{
	return x1.pos0)
		{
			a[i].cor=a[i].val;
			x--;
			continue;
		}
		if (n-i+n-y<2*a[i].sam) 
		{
			printf("NO\n");
			return;
		}
		num=i;len=n-i;break;//两个指标都用完了,代表着还有num个数需要周旋。 
	}

	//第三次排序 ,按大小排序,这样就可以优先更换same大的 
	sort(a+num,a+n,cmp1);
	for (int i=num;i0&&a[i].cor!=unuse[0])
		{
			a[i].cor=unuse[0];
			tmp--;
		}
	}
	//最后一次排序,按地址排回来
	print();
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)rlmn();
	return 0;
}

 

你可能感兴趣的:(算法训练)