码迷,mamicode.com
首页 > 其他好文 > 详细

CF1381B Unmerge

时间:2020-07-26 01:18:18      阅读:58      评论:0      收藏:0      [点我收藏+]

标签:fine   tchar   div   假设   puts   spl   逆向   get   tor   

Unmerge,题意差不多就是逆向归并排序

手模样例,3 1 2 4 ,发现这个 3 肯定是 a 或 b 的第一个字母,然后假设把 3 放在 a 的第一个,那么 1 放 b 的第一个就不行,只能放 3 后面,2 也是同理,直到 4 才可以放在 b 。按照这个结论去模拟了所有样例,发现没啥问题。于是我们发现,如果选一个数,那么从这个数开始后面,直到第一个比他大的数前为止的数都必须得选。那么这个题就转化成了:

给定一些数,求把他们分成和相等的两组是否可行

可行性dp走起: \(f_{i,j}=true/false\) 表示使用前 \(i\) 个数, a 组的数的和减去 b 组的数的和是否可能到达 \(j\) ,然后转移方程显而易见:

\[f_{i,j} \leftarrow f_{i-1,j+a_i} | f_{i-1,j-a_i} \]

这个显然可以滚存,然后bitset一下,代码就非常短了

// This code wrote by chtholly_micromaker(MicroMaker)
#include <bits/stdc++.h>
#define reg register
using namespace std;
template <class t> inline void read(t &s)
{
	s=0;
	reg int f=1;
	reg char c=getchar();
	while(!isdigit(c))
	{
		if(c==‘-‘)
			f=-1;
		c=getchar();
	}
	while(isdigit(c))
		s=(s<<3)+(s<<1)+(c^48),c=getchar();
	s*=f;
	return;
}
int a[4000];
inline void work()
{
	int n;read(n);
	n<<=1;
	for(int i=1;i<=n;++i)
		read(a[i]);
	vector<int> dr;
	for(int i=1;i<=n;++i)	// 把问题转化
	{
		reg int pos=i;
		while(pos<n&&a[pos+1]<a[i])
			++pos;
		dr.push_back(pos-i+1);
		i=pos;
	}
	bitset<4000> f;		// 可行性dp
	f[2000]=true;
	for(int i=0;i<(int)dr.size();++i)
		f=(f<<dr[i])|(f>>dr[i]);
	puts(f.test(2000)?"YES":"NO");
	return;
}
signed main(void)
{
	int t;cin>>t;
	while(t--)
		work();
	return 0;
}

CF1381B Unmerge

标签:fine   tchar   div   假设   puts   spl   逆向   get   tor   

原文地址:https://www.cnblogs.com/chinesepikaync/p/13378106.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!