#658 (Div. 2)D.Unmerge(分块+01背包问题)

题目描述

Let a and b be two arrays of lengths n and m, respectively, with no elements in common. We can define a new array merge(a,b) of length n+m recursively as follows:
If one of the arrays is empty, the result is the other array. That is, merge(∅,b)=b and merge(a,∅)=a. In particular, merge(∅,∅)=∅.
If both arrays are non-empty, and a1<b1, then merge(a,b)=[a1]+merge([a2,…,an],b). That is, we delete the first element a1 of a, merge the remaining arrays, then add a1 to the beginning of the result.
If both arrays are non-empty, and a1>b1, then merge(a,b)=[b1]+merge(a,[b2,…,bm]). That is, we delete the first element b1 of b, merge the remaining arrays, then add b1 to the beginning of the result.
This algorithm has the nice property that if a and b are sorted, then merge(a,b) will also be sorted. For example, it is used as a subroutine in merge-sort. For this problem, however, we will consider the same procedure acting on non-sorted arrays as well. For example, if a=[3,1] and b=[2,4], then merge(a,b)=[2,3,1,4].
A permutation is an array consisting of n distinct integers from 1 to n in arbitrary order. For example, [2,3,1,5,4] is a permutation, but [1,2,2] is not a permutation (2 appears twice in the array) and [1,3,4] is also not a permutation (n=3 but there is 4 in the array).
There is a permutation p of length 2n. Determine if there exist two arrays a and b, each of length n and with no elements in common, so that p=merge(a,b).

Input

The first line contains a single integer t (1≤t≤1000) — the number of test cases. Next 2t lines contain descriptions of test cases.
The first line of each test case contains a single integer n (1≤n≤2000).
The second line of each test case contains 2n integers p1,…,p2n (1≤pi≤2n). It is guaranteed that p is a permutation.
It is guaranteed that the sum of n across all test cases does not exceed 2000.

Output

For each test case, output “YES” if there exist arrays a, b, each of length n and with no common elements, so that p=merge(a,b). Otherwise, output “NO”.

Example

Input
6
2
2 3 1 4
2
3 1 2 4
4
3 2 6 1 5 7 8 4
3
1 2 3 4 5 6
4
6 1 3 7 4 5 8 2
6
4 3 2 5 1 11 9 12 8 6 10 7
Output
YES
NO
YES
YES
NO
NO

Note

In the first test case, [2,3,1,4]=merge([3,1],[2,4]).
In the second test case, we can show that [3,1,2,4] is not the merge of two arrays of length 2.
In the third test case, [3,2,6,1,5,7,8,4]=merge([3,2,8,4],[6,1,5,7]).
In the fourth test case, [1,2,3,4,5,6]=merge([1,3,6],[2,4,5]), for example.

题目大意

定义两个数组的合并运算为 每次取出两个数组中第一个元素较大的那一个放入新数组,现给出一个长度为 2 * n 的置换数组,问 能不能找到两个长度为 n 的置换数组合并后为原数组 。

题目分析

我们可以将给定的数组a[]进行分块,如:[3 2 6 1 5 7 8 4]可以分成[3 2] [6 1 5] [7] [8 4]四块。分割方法:为了能使每一块在进行比较时能连续的全部放入数组中,我们分块时可以先将第一个数放入一块,如果下一个数小于该数,则继续放入这一块,直到某个数大于第一个数,那么这个数就是一个新块的第一个数,以此类推。
按这样的方法分好块之后,这个问题就转化为了一个背包问题了:一共有m个块,背包的容量为n,每个物品的体积为b[i],问从这些物品中选取一些,能否刚好装满这个背包。用01背包的做法求一下最后的f[n]是否刚好为n就行了。

代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <iomanip>
#define LL long long
#define PII pair<int,int>
using namespace std;
const int N=1e4+5;
int a[N],f[N];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		vector<int> b;
		int n;
		cin>>n;
		for(int i=1;i<=2*n;i++)
			cin>>a[i];
		
		int max=a[1],cnt=1;		//分块过程,max记录当前块的最大值,cnt记录块的长度
		for(int i=2;i<=2*n;i++)
		{
			if(max<a[i])
			{
				max=a[i];
				b.push_back(cnt);
				cnt=0;
			}
			cnt++;
		}
		memset(f,0,sizeof f);
		for(int i=0;i<b.size();i++)		//dp求解答案
			for(int j=n;j>=b[i];j--)
				f[j]=std::max(f[j],f[j-b[i]]+b[i]);
		
		f[n]==n?puts("YES"):puts("NO");
	}
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwz_159

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值