CodeForces_1381B Unmerge(动态规划)

Unmerge

time limit per test:1 seconds
memory limit per test:256 megabytes
Problem Description

Let a a a and b b b be two arrays of lengths n n n and m m m, respectively, with no elements in common. We can define a new array merge ( a , b ) (a,b) (a,b) of length n + m n+m n+m recursively as follows:

  • If one of the arrays is empty, the result is the other array. That is, merge ( ∅ , b ) = b (∅,b)=b (,b)=b and merge ( a , ∅ ) = a (a,∅)=a (a,)=a. In particular, merge ( ∅ , ∅ ) = ∅ (∅,∅)=∅ (,)=.
  • If both arrays are non-empty, and a 1 < b 1 a_1<b_1 a1<b1, then merge ( a , b ) = [ a 1 ] + m e r g e ( [ a 2 , … , a n ] , b ) (a,b)=[a_1]+merge([a_2,…,a_n],b) (a,b)=[a1]+merge([a2,,an],b). That is, we delete the first element a 1 a_1 a1 of a a a, merge the remaining arrays, then add a 1 a_1 a1 to the beginning of the result.
  • If both arrays are non-empty, and a 1 > b 1 a_1>b_1 a1>b1, then m e r g e ( a , b ) = [ b 1 ] + m e r g e ( a , [ b 2 , … , b m ] ) merge(a,b)=[b_1]+merge(a,[b_2,…,b_m]) merge(a,b)=[b1]+merge(a,[b2,,bm]). That is, we delete the first element b 1 b_1 b1 of b b b, merge the remaining arrays, then add b 1 b_1 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 ] a=[3,1] a=[3,1] and b = [ 2 , 4 ] b=[2,4] b=[2,4], then m e r g e ( a , b ) = [ 2 , 3 , 1 , 4 ] merge(a,b)=[2,3,1,4] 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 ] [2,3,1,5,4] [2,3,1,5,4] is a permutation, but [ 1 , 2 , 2 ] [1,2,2] [1,2,2] is not a permutation (2 appears twice in the array) and [ 1 , 3 , 4 ] [1,3,4] [1,3,4] is also not a permutation ( n = 3 n=3 n=3 but there is 4 in the array).

There is a permutation p of length 2 n 2n 2n. Determine if there exist two arrays a a a and b b b, each of length n and with no elements in common, so that p = m e r g e ( a , b ) p=merge(a,b) p=merge(a,b).

Input

The first line contains a single integer t t t ( 1 ≤ t ≤ 1000 1≤t≤1000 1t1000) — the number of test cases. Next 2 t 2t 2t lines contain descriptions of test cases.

The first line of each test case contains a single integer n n n ( 1 ≤ n ≤ 2000 1≤n≤2000 1n2000).

The second line of each test case contains 2 n 2n 2n integers p 1 p_1 p1,…, p 2 n p_{2n} p2n ( 1 ≤ p i ≤ 2 n 1≤p_i≤2n 1pi2n). It is guaranteed that p is a permutation.

It is guaranteed that the sum of n n n across all test cases does not exceed 2000 2000 2000.

Output

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

Sample 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

Sample Output

YES
NO
YES
YES
NO
NO

题意

两个长度为n的序列a和b,a和b中所有的元素互异。现在将两个序列合并为一个序列。每次比较两个序列的首元素,将首元素较小的放入新序列的尾部,并将该元素从原序列删除。给出最后得到的序列,按照规则,是否能找出满足条件的两个数组a,b.

题解

对于合并后的序列,其首元素为x,则之后的连续的所有小于x的数,和x一定属于同一个序列。因为x在首位,则另一个序列的首元素一定大于x。所以将给出的序列分组,将数x以及之后连续的小于x的元素作为一组。如 [ 2 , 3 , 1 , 4 ] [2,3,1,4] [2,3,1,4],可分为 [ 2 ] [ 3 , 1 ] [ 4 ] [2][3,1][4] [2][3,1][4].
统计各组元素的数量,动态规划,判断是否能选取若干组,使其元素和为n即可。

#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-6
   
using namespace std;
typedef unsigned long long LL;  
typedef pair<LL, int> P;
const int maxn = 4020;
const LL mod = 2000000007;
int a[maxn], b[maxn], dp[maxn];

int main()
{
    int t, n, m, i, j, k, top;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        for(i=0;i<2*n;i++)
            scanf("%d", &a[i]);
        i = top = 0;
        while(i<2*n)
        {
            j = i+1;
            while(j<2*n && a[j]<a[i])j++;
            b[top++] = j-i;
            i = j;
        }
        memset(dp, 0, sizeof(dp));
        dp[0] = 1;
        for(i=0;i<top;i++)
            for(j=2*n;j>=0;j--)
                if(dp[j])dp[j+b[i]] = 1;
        if(dp[n])printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值