Unequal Array(贪心/双指针/思维)

博客探讨了一个关于数组操作的问题,给定两个数组a和b,其中b是a的排列,通过特定操作判断是否能将a转换为b。文章提出了一种反向思考的解决方案,使用 multiset 对b中的重复元素进行存储,并在遍历过程中检查转换的可能性。该算法在C++中实现,主要涉及数组处理和集合操作,对于理解数组操作和算法设计有一定帮助。
摘要由CSDN通过智能技术生成

题目
题意:给定长度为 n n n的数组 a , b a,b a,b,其中数组 b b b是数组 a a a的一个排列。数组 a a a可以执行以下操作:

  • 选择 1 < = l < r < = n 1<=l<r<=n 1<=l<r<=n a l = = a r a_l==a_r al==ar,令 a l , a l + 1 . . . , a r − 1 , a r = a l + 1 , . . . , a r , a l a_l,a_{l+1}...,a_{r-1},a_r=a_{l+1},...,a_r,a_l al,al+1...,ar1,ar=al+1,...,ar,al

通过以上若干次操作后,问数组 a a a能否转换为 b b b

参考

思路:每次操作,相当于选择两个相同的元素 a l , a r a_l,a_r al,ar,删除 a l a_l al,并把元素 a r a_r ar复制一次。
考虑逆过来思考这个过程。相当于 b b b数组中,选择相等的两个相邻元素 b i , b i + 1 b_i,b_{i+1} bi,bi+1,删除其一,并把另一个元素丢到前面任意位置。问最终 b b b能否转化为 a a a

我们从分别用下标 i , j i,j i,j大到小遍历数组 a , b a,b a,b,在遍历过程中存储b中重复的元素 b j b_j bj S S S备用;如果 b j = = a i b_j==a_i bj==ai,则检查它们下一个元素;如果 b j ! = a i b_j!=a_i bj!=ai,则看 S S S是否存在元素等于 a i a_i ai,存在则取出,不存在,则说明无解,即 b b b不能转换为 a a a

在#include <bits/stdc++.h> 
using namespace std;
const int maxn = 200010;

int a[maxn], b[maxn];
int n, m;
multiset<int> st;
void solve() {
	st.clear();
	scanf("%d", &n);
	for (int i = 0; i < n; ++i) {
		scanf("%d", &a[i]);
	}
	for (int i = 0; i < n; ++i) {
		scanf("%d", &b[i]);
	}
	int i = n - 1, j = n - 1;
	bool ok = true;
	while (i >= 0 && ok) {
		while (j && b[j] == b[j-1]) {
			st.insert(b[j]);
			--j;
		}
		if (j >= 0 && b[j] == a[i]) {
			--i;--j;
		} else if (st.find(a[i]) != st.end()){
			st.erase(st.find(a[i]));
			--i;
		} else {
			ok = false;
		}
	}
	printf("%s\n", ok ? "YES" : "NO");
}

int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		solve();
	}
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值