6.25 Codeforces Round 练习

本文讨论了三个与数组排列相关的问题:1. 奇数个数圆周数组的重新排列;2. 交换操作使数组变为非递减;3. 混合数组的LCS策略。通过分析,提供了相应的解决思路和代码实现,涉及贪心算法、排序和最长公共子序列等技术。
摘要由CSDN通过智能技术生成

c

  • 题目:
  • 给你数组A,里面有n个数字,n个数字呈圆形排列,将A重新排列使得重新排列之后的每个位置的数字b[i]必须符合以下两个条件之一:
    1 b[i - 1] < b[i] > b[i + 1]
    2 b[i - 1] > b[i] < b[i + 1]
    问能不能找到至少一种排列满足以上条件.
  • 思路:
  • 对于给出的数字n,如果n是奇数,那不可能存在一种排列满足上述条件: 因为是呈圆形排列,所以从哪一个位置开始都可以,这里我们可以先从第一个位置开始,先假设位置1的数字满足第一个条件,即必须符合 b[n] < b[1] > b[2], b[1] > b[2] < b[3]…我们可以看出来下标是奇数的,就是符合条件1,下标是偶数的符合条件2,因为n是奇数,所以最后一定是 b[n - 1]<b[n] > b[1],然后与前面b[n] < b[1] > b[2]相冲突,所以奇数一定不可行,同理如果位置1的数字符合第二个条件也是如此,会冲突
  • 对于偶数的话,因为从题目我们可以知道这个数列如果画图的话满足的其实是一个 WWWWW 或者 是一个 MMMMM的排列,就是峰顶的一定大于两边的峰底,峰底的一定小于两遍的峰顶 为了使得每一个数字都满足这个条件,我们可以对这个数列排序,让前面的一半做峰底,后面的一半做峰顶,这样就满足前面说的条件了,同时必须满足贪心的思想,就是先排列峰顶峰底的最小值,这样才可以使得数列尽可能的往后面填值,所以填充顺序就是a[0],a[n / 2],a[1],a[n / 2 + 1]…
  • 代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define PII pair<int,int>
#define int long long 
#define ios ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr)
using namespace std;

void solve()
{ 
	int n; cin >> n;
	vector<int>a(n),b;
	for(int i = 0;i < n;i ++ ) cin >> a[i];
	
	if(n % 2 == 1)
	{
	     cout << "NO" << endl;
	     return;
	}


	sort(all(a));
	for(int i = 0,j = n / 2;j < n;i ++ ,j ++ )
	{
		b.pb(a[i]);//大 
		b.pb(a[j]);//小 
	}
	b.pb(a[0]);
	bool f = true;
	for(int i = 1;i < b.size();i += 2 )
	{
	
			if(b[i] <= b[i - 1] || b[i] <= b[i + 1]) 
			{
			    f = false;
			}
	
	}
    
    if(f)
	cout << "YES" << endl;
	else
	cout << "NO" << endl;
	
	if(f)
	{
	for(int i = 0;i < n;i ++ )
	cout << b[i] << ' ';
	cout << endl; 
	}
	b.clear();
	
	
}
signed main() 
{
	ios;int T; cin >> T;
	while(T -- ) solve();

    return 0;
}
  • 题目:
    给你两个数组a,b,每次你可以选择两个不同的下标i,j,交换a[i]和a[j],b[i]和b[j],问有没有可能使得这两个数组变成非递减数组?
  • 思路:
    我们可以先考虑a数组,不管b数组,使得a数组排好序以后,再来考虑b数组,此时的b数组如果其中还有元素不符合条件的话,就要看不符合条件的元素对应的a数组的元素是不是相等了,如果相等,才可以交换,只要出现b数组中的某些元素不符合条件,同时对应的a数组中的元素不等.就一定无法交换元素.
  • 代码:

```cpp
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define PII pair<int,int>
#define int long long 
#define ios ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr)
using namespace std;

void solve()
{ 
	int n; cin >> n;
	
	vector<int> a(n),b(n);
	vector<PII> res;
	for(int i = 0;i < n;i ++ ) cin >> a[i];
	for(int i = 0;i < n;i ++ ) cin >> b[i];
	
	for(int i = 0;i < n - 1;i ++ )
	{
		int id = i;
		for(int j = i + 1;j < n;j ++ )
		{
			if(a[j] <= a[id])
			{
				id = j;	
			}
		}
		
		if(i != id)
		{
			swap(a[i],a[id]);
			swap(b[i],b[id]);
			res.pb({i,id});
		}
		
	}
	
	for(int i = 0;i < n - 1;i ++ )
	{
		int id = i;
		for(int j = i + 1;j < n;j ++ )
		{
			if(b[j] < b[id])
			{
				id = j;	
			}
		}
		
		if(i != id && a[i] == a[id])
		{
			swap(b[i],b[id]);
			res.pb({i,id});
		}
		else if(i != id && a[i] != a[id])
		{
			cout << "-1" << endl;
			return;
		}
		
	}
	cout << res.size() << endl;
	for(auto x:res)
	cout << x.fi + 1<< ' ' << x.se + 1 << endl;

}
signed main() 
{
	ios;int T; cin >> T;
	while(T -- ) solve();
//we
    return 0;
}
  • 题目:
    给你一个数组a,同时定义一个数组b,b的元素是a翻转之后的元素,将LCS定义为一个数组中的最长上升子序列,打乱a的排列顺序,使得你能找出一种排列求出min(LCS(a),LCS(b))中的最大值
  • 思路:
    这道题首先分析,对于一个数字,要么是插入里面LCS(a)里面要么插入LCS(b)里面,要么两者都插入,如果该数字的个数只有一个的话,只能插入到一个里面,如果该数字的个数 >= 2的话就可以两个都插入,但是如果个数是 > 2的话,多余的就没有必要插入了,因为多余的插入并不会改变LCS(a)的长度和LCS(b)的长度,所以只统计数字的个数<=2的个数就行,如果只有数字的个数只有一个的数字一共有奇数个,那总共的有效数列长度就是ans + 1,答案就是(ans + 1) / 2,如果是偶数个的话就是ans / 2,
  • 代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define PII pair<int,int>
#define int long long 
#define ios ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr)
using namespace std;
const int N = 2e5 + 100;

void solve()
{ 
	int n; cin >> n;
	int ans = 0;map<int,int> mp;
	for(int i = 1;i <= n;i ++ )
	{
		int x; cin >> x;
		mp[x]++;
		
		if(mp[x] <= 2)
		ans++; 
	}
	

	cout << (ans + 1)/ 2 << endl;

	
	
}
signed main() 
{
	ios;int T; cin >> T;
	while(T -- ) solve();

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值