Codeforces Round #658 (Div. 2) D. Unmerge (思维,01背包)
2024-08-31 07:36:13
题意:有两个数组\(a\)和\(b\),每次比较它们最左端的元素,取小的加入新的数组\(c\),若\(a\)或\(b\)其中一个为空,则将另一个全部加入\(c\),现在给你一个长度为\(2n\)的数组\(c\),问是否能有两个长度为\(n\)的数组\(a\)和\(b\)构成.
题解:我们从左向右看\(c\),记一个最大值\(mx\),观察样例不难发现,跟随在\(mx\)后面比\(mx\)小的元素,它们一定来自同一个数组,比如第三个样例:
3 2 6 1 5 7 8 4
\(3,2\)一定来自同一个数组,\(6,1,5\)一定来自同一个数组,\(7\)就一个元素,\(8,4\)一定来自同一个数组,所以我们将它们分段,\((3,2)\),\((6,1,5)\),\((7)\),\((8,4)\).我们要在这些之间凑出一个元素长度为\(n\)的数组即可,这里我们用01背包来解决,我们背包的最大容量为\(n\),去看是否能填满.
代码:
int t;
int n;
int a[N];
vector<int> v;
int dp[N]; int main() {
scanf("%d",&t);
while(t--){
scanf("%d",&n);
me(dp,0,sizeof(dp));
v.clear();
for(int i=1;i<=2*n;++i){
scanf("%d",&a[i]);
}
int mx=a[1];
int pos=1;
for(int i=2;i<=2*n;++i){
if(a[i]>mx){
v.pb(i-pos);
mx=a[i];
pos=i;
}
}
v.pb(2*n+1-pos); for(int i=0;i<v.size();++i){
for(int j=n;j>=v[i];--j){
dp[j]=max(dp[j],dp[j-v[i]]+v[i]);
}
}
if(dp[n]==n) puts("YES");
else puts("NO"); } return 0;
}
最新文章
- MongoDB与PostgresQL无责任初步测试
- 论SCRM系统对传统行业的冲击
- apk支持html video控制 ,是播放状态就暂停,暂停状态就播放
- Sql Server 事务隔离级别的查看及更改
- bzoj 2806: [Ctsc2012]Cheat 后缀自动机DP
- jetty服务器
- 我想要个pc和手机共有的客户端,就像百度云(iBarn网盘好用)
- Windows搭建Sublime Text 3 + Go开发环境
- 洛谷-三连击(升级版)-BOSS战-入门综合练习1
- sqlite数据库之简单操作
- nodejs-url网址解析的好帮手
- Java实现栈之计算器
- docker load 镜像时出现:open /var/lib/docker/tmp/docker-import-500852078/repositories: no such file or dir
- react 入坑笔记(四) - React 事件绑定和传参
- 手机连接WiFi有感叹号x怎么回事?如何消除手机WiFi感叹号?
- BarTender怎样同时打印自动日期和流水号?
- 【vs2010】转换到 COFF 期间失败: 文件无效或损坏
- Linux partprobe命令详解
- arm-linux-gcc配置安装
- lintcode-65-两个排序数组的中位数