题解 合并 union
合并 union
Description
给出一个 1 ∼ N 的序列 A ( A 1 , A 2 , ..., A N ) 。你每次可以将两个相邻的元素合并,合并后的元素权值即为 这两个元素的权值之和。求将 A 变为一个非降序列,最少需要多少步操作。
Input
输入的第一行一个整数 N ( N ≤ 5000) 。
接下来一行 N 个整数,描述序列 A 。保证序列 A 中的每个元素的值不超过 1000 。
Output
输出一行一个整数,表示最少的操作数。
Sample Input
5
9 7 5 13 15
Sample Output
1
解析
这题很明显是用DP啊啊啊!!
我们设\(f[i]\)表示将序列\(1\)~\(i\)合并的最小次数,
\(g[i]\)表示将序列\(1\)~\(i\)合后的最后一个元素的权值,
那么,从\(1\)到\(n\)枚举\(i\),
再从\(i\)~\(1\)枚举\(j\),表示将$ j\(~\)i\(合并成一个点,再添加到已经合并完后的序列\) 1\(~\)j$-\(1\)后面,
什么?你问我为什么要将$ j\(~\)i$合并成一个点?
仔细想一下,如果有一个\(k\),并且将\(j\)~\(k\)合并,再将\(k\)+$1 \(~\)i$合并后会使答案更优,
那么在枚举到\(k\)时,就会将当前情况统计一次,
而在枚举\(i\)时,当\(j\)枚举到\(k\)时,就会统计到这个答案了!!(口胡证明可能有点乱,自己画图理解下哈).
然后,我们考虑状态转移,
如果\(g[i-1]\)<=\(a[i]\)-\(a[j-1]\)(\(a\)为前缀和,表示\(i\)到\(j\)合并后的权值,整个式子就表示\(i\)到\(j\)合并后能接到\(j\)-\(1\)后面).
并且\(f[j-1]\)+\((i-j)\)<=\(f[i]\)(即次数更少,(\(i\)-\(j\))表示将\(j\)~\(i\)合并成\(1\)个点的次数),
那么我们就更新\(f[i]\)和\(g[i]\),\(g[i]\)就是\(j\)~\(i\)合成的点的权值.
那么最后,\(f[n]\)即为答案.
不清楚的看代码吧:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return f*sum;
}
int n,a[100001];
int f[100001],g[100001];
int main(){
n=read();
memset(f,0x3f,sizeof(f));f[0]=0;
for(int i=1;i<=n;i++) g[i]=read();//并没什么用但也没影响,只是存一下权值
for(int i=1;i<=n;i++) a[i]=g[i]+a[i-1];//前缀和
for(int i=1;i<=n;i++){
for(int j=i;j;j--){
if(g[j-1]<=a[i]-a[j-1]){
if(f[j-1]+i-j<f[i]){//更新
f[i]=f[j-1]+i-j;
g[i]=a[i]-a[j-1];
}
}
}
}
printf("%d\n",f[n]);
return 0;
}
题解 合并 union的更多相关文章
- sql语句查询结果合并union all用法
整理别人的sql 大概的思想是用union 和union all --合并重复行select * from Aunion select * from B --不合并重复行select * from A ...
- 【DP合集】合并 union
给出一个 1 ∼ N 的序列 A ( A 1 , A 2 , ..., A N ) .你每次可以将两个相邻的元素合并,合并后的元素权值即为 这两个元素的权值之和.求将 A 变为一个非降序列,最少需要多 ...
- sql语句查询结果合并union all用法_数据库技巧
--合并重复行 select * from A union select * from B --不合并重复行 select * from A union all select * from B 按某个 ...
- mysql sql语句多表合并UNION ALL和UNION
select d1.ID,CAST(d1.ID AS CHAR) AS intId, d1.CODE_TYPE, d1.CODE, d1.CODE_IMG, d1.VALUE from m_dict_ ...
- LeetCoded第21题题解--合并两个有序链表
21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出 ...
- 8.2.1.4 Index Merge Optimization 索引合并优化:
8.2.1.4 Index Merge Optimization 索引合并优化: 索引合并方法是用于检索记录 使用多个 范围扫描和合并它们的结果集到一起 mysql> show index fr ...
- MySQL 数据底部出现总计字样 第二种办法 纵向合并 20161103
上次在博客http://www.cnblogs.com/Mr-Cxy/p/5923375.html 我们使用了group by with rollup 函数 field自定义排序 来实现添加底部总计字 ...
- 并查集 (Union Find ) P - The Suspects
Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized ...
- [SQL 高级查询运算符的用法 UNION (ALL),EXCEPT(ALL),INTERSECT(ALL) ]
今天看到 三个查询运算符,给大家分享分享 为此我建立了两张表分别为 Articles 和 newArticles 我建立的时候,只建立了一张表 Articles ,表 newArticles 是 ...
随机推荐
- PAT B1011 A+B 和 C (15)
AC代码 #include <cstdio> int main() { int T, tcase = 1; scanf("%d", &T); for(int i ...
- centos 秘钥登录
客户端系统:macOS 服务端系统:Centos7 另外:ip 为 172.25.11.182 用户名为 iamfine 1, 在客户端macOS上生成 rsa 对 ssh-keygen -t rsa ...
- python-迭代器实现异步(在串行中)
import timedef consumer(name): print('%s 准备吃包子啦!' %name) while True: baozi = yield #yield不但可以返回值还可以接 ...
- Nginx、OpenResty和Kong的基本概念与使用方法
Nginx.OpenResty和Kong的基本概念与使用方法 2018年10月10日 22:46:08 李佶澳 阅读数 322更多 分类专栏: kubernetes 版权声明:本文为博主原创文章, ...
- spring-cloud 学习二 服务发现
注册中心服务发现的例子 添加module pom文件如下 <?xml version="1.0" encoding="UTF-8"?> <pr ...
- 作业2:java内存模型图示
参考:http://www.infoq.com/cn/minibooks/java_memory_model?utm_source=infoq&utm_campaign=user_page&a ...
- O038、Shelve Instance 操作详解
参考https://www.cnblogs.com/CloudMan6/p/5524751.html Instance 被 Suspend 后虽然处于 shutdown 状态,但 Hypervis ...
- CF516D Drazil and Morning Exercise
cf luogu 首先每个点到最远点的距离可以预处理出来,这个距离显然是这个点到树直径两端点的最大值.把那个距离记为\(d_i\),然后从小到大枚举\(d_i\),并强制它为最大的\(d_i\),那么 ...
- Springboot Hikari Centos 首次连数据库很慢
前言: springboot项目默认使用了hikari作为数据库连接池,在开发机器上一切正常. 但是把程序部署到Centos7 x64上之后发现,每次首页登录的时候都要停顿几十秒. 于是,在程序启动后 ...
- vue项目使用openlayers来添加地图标注,标注样式设置的简要模板
先把代码贴出来,注释以后有时间再写(需要留意一下这里图标的引入方式,函数内相同路径无法找到图片) import sk from "../../assets/img/home/sk-activ ...