codeforces1381B Unmerge

https://codeforces.com/problemset/problem/1381/B

这题只会n^3,掉大分。hwh:这不是显然的结论吗,人尽皆知啊

我们判断是否可以组成满背包

优先拿更短的物品去更新,如果更短的物品跟更长物品,可以只考虑这个更短的物品,也就是说,分组背包中一个组内,只考虑最短的物品就更新背包容量dp数组会更容易得到更多的位置能被组成。

要知道这题的结论就是下一段数的首数字要大于上一段数字的全部,而且序列分段是连续不重叠的,于是如果能够1-2,1-3,1-4,那么必然可以1-3,4-4,所只要找到最近的能更新的部分去刷新dp数组就可以了。所以整个区间最多被贪心地分成n段,所以一共只有n个物品,且互不冲突

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;

const int maxl=4010;

int n,m,cas,k,cnt,tot,ans;
int a[maxl];
bool dp[maxl];
char s[maxl];
bool in[maxl]; 

inline void prework()
{
	scanf("%d",&n);
	for(int i=1;i<=2*n;i++)
		scanf("%d",&a[i]);
} 

inline void mainwork()
{
	a[2*n+1]=2*n+1;dp[0]=true;
	for(int i=1;i<=n;i++) dp[i]=false;
	int mx,len;
	for(int i=1;i<=2*n;i++)
	{
		mx=a[i];
		for(int j=i;j<=2*n;j++)
		{
			mx=max(a[j],mx);len=j-i+1;
			if(a[j+1]>mx)
			{
				for(int w=n;w>=len;w--)
					dp[w]|=dp[w-len];
				i=j;
				break;
			}
		}
	}
}

inline void print()
{
	if(dp[n])
		puts("YES");
	else
		puts("NO");
}

int main()
{
	int t=1;
	scanf("%d",&t);
	for(cas=1;cas<=t;cas++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/107525030