计蒜之道 百度AI小课堂-上升子序列

题目描述

给一个长度为 \(n\) 的数组 \(a\) 。试将其划分为两个严格上升子序列,并使其长度差最小。

输入格式

输入包含多组数据。

数据的第一行为一个正整数 \(T\) ,表示数据组数。

每组数据包括两行:

第一行包括一个正整数 \(n\)

第二行包括一个长度为 \(n\) 的数组 \(a\)。

输出格式

对于每组数据输出一行一个整数,表示两个子序列的最小长度差。若不存在划分方案则输出\(-1\)

数据范围

\(T <= 10\)

简单: \(n <= 10^5, 0 <= a_i <= 2^{30}\), 最多只存在一种合法的划分方案

中等: \(n <= 10^3, 0 <= a_i <= 2^{30}\), 划分方案不超过\(10^{18}\)

困难: \(n <= 10^5, 0 <= a_i <= 2^{30}\), 划分方案不超过\(10^{18}\)

思路:直接上题解

如果一个位置\(k\)满足对于\(∀_i∈[1,k], ∀_j∈[k+1,n], a_i < a_j\)恒成立,那么称\(k\)为一个分界点。找出所有分界点后可将序列分为若干段,每段之间相互独立,同时每段只存在不超过一种合法的方案数。求出每段的划分\(O(n)\),再进行背包dp(\(O(nlogK)\)(\(K\)为可能的划分方案数))

其实就是说对于某个\(i\),满足\(max(1,i) < min(i + 1,n)\),则序列\([1,i]和[i+1,n]\)是相互独立的。

同理再来一个\(j > i\) 满足\(max(1,j) < min(j + 1,n)\), 则序列\([1,j]和[j+1,n]\)相互独立, 序列\([1,i]\)已经被划分出去,所以左边剩下\([i+1,j]\)。

简单证明这样的每段如果合法,只存在一种划分。

即证明对于合法的一段\([i,j](j > i + 1)\), 若不存在\(k\),满足\(i<=k<j, max(i,k) < min(k+1,j)\),那么段\([i,j]\)只有一种划分方案。

反证不存在的情况有多种划分成立, 则存在的情况下只有一种划分,存在的情况下可以分成不可再分的几段,每段有多种划分,拼起来也会有多种划分, 与只有一种划分矛盾。

每段只有一种划分, \(m\)段组合起来的方案数为\(2^m = K\), 所以\(m = logK\)

最后问题变成一个背包,从每段中选择一个序列长度组合起来,最后是否出现长度为\(j\)的序列(\(dp[j]\))

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int INF = 1e9;
const int N = 1e5 + 10;
int a[N];
int mi[N], mx[N];
int dp[2][N];
int T, n, o;
bool gao(int l, int r){
int first = 0, second = 0, cnt = 0;
for(int i = l;i <= r;i++){
if(first < a[i]) first = a[i], cnt++;
else if(second < a[i]) second = a[i];
else return false;
}
int d[2] = {cnt, r - l + 1 - cnt};
for(int i = 0;i <= n;i++) {
dp[o ^ 1][i] = 0;
for(int k = 0;k < 2;k++){
if(i >= d[k]) dp[o ^ 1][i] |= dp[o][i - d[k]];
}
}
o ^= 1;
return true;
}
int main(){
cin>>T;
while(T--){
cin>>n;
for(int i = 1;i <= n;i++) cin>>a[i];
if(n == 1){
cout<<-1<<endl;
continue;
}
mx[0] = -1, mi[n + 1] = (1<<30) + 1;
for(int i = 1;i <= n;i++) mx[i] = max(mx[i - 1], a[i]);
for(int i = n;i >= 1;i--) mi[i] = min(mi[i + 1], a[i]);
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
int last = 1;
bool flag = true;
o = 0;
for(int i = 1;i <= n;i++){
if(mx[i] < mi[i + 1]){
if(!gao(last, i)){
flag = false;
break;
}
last = i + 1;
}
}
int ans = -1;
if(flag){
for(int i = n / 2;i >= 0;i--) if(dp[o][i]){
ans = n - 2 * i;
break;
}
}
cout<<ans<<endl;
}
}

计蒜之道 百度AI小课堂-上升子序列的更多相关文章

  1. 2019 计蒜之道 初赛 第二场 B. 百度AI小课堂-上升子序列(简单) ( 实现)

    题目背景 ​91029102 年 99 月 22 日,百度在 X 市 XX 中学举办的第一场 AI 知识小课堂大获好评!同学们对矩阵的掌握非常棒. 今天的 AI 知识小课堂的第二场开讲啦.本场 AI ...

  2. 2019 计蒜之道 初赛 第二场 A 百度AI小课堂-矩阵问题 ( 等差数列求和公式)

    题目背景 ​91029102 年 99 月 11 日,百度在 X 市 XX 中学举办了一场 AI 知识小课堂,本场 AI 知识小课堂老师教授了一些矩阵的相关知识,因为矩阵在 AI 人工智能中也有相当的 ...

  3. 2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)

    贝壳找房在遥远的传奇境外,找到了一个强大的魔法师顾问.他有 22 串数量相同的法力水晶,每个法力水晶可能有不同的颜色.为了方便起见,可以将每串法力水晶视为一个长度不大于 10^5105,字符集不大于  ...

  4. [计蒜之道2019 复赛 A]外教 Michale 变身大熊猫

    [计蒜之道2019 复赛 A]外教 Michale 变身大熊猫 Online Judge:2019计蒜之道 复赛 A Label:LIS+线段树.树状数组+快速幂(模逆元) 题目描述 题解: pre. ...

  5. 2019计蒜之道初赛4 B. 腾讯益智小游戏—矩形面积交(简单)(矩形交集)

    B. 腾讯益智小游戏—矩形面积交(简单) 1000ms 262144K   腾讯游戏开发了一款全新的编程类益智小游戏,最新推出的一个小游戏题目是关于矩形面积交的.聪明的你能解出来吗?看下面的题目接招吧 ...

  6. 2019 计蒜之道 初赛 第一场 商汤AI园区的n个路口(中等) (树形dp)

    北京市商汤科技开发有限公司建立了新的 AI 人工智能产业园,这个产业园区里有 nn 个路口,由 n - 1n−1 条道路连通.第 ii 条道路连接路口 u_iui​ 和 v_ivi​. 每个路口都布有 ...

  7. 2019计蒜之道初赛第3场-阿里巴巴协助征战SARS 费马小定理降幂

    题目链接:https://nanti.jisuanke.com/t/38352 发现规律之后就是算ans=2^(n-1)+4^(n-1).但是注意到n十分大是一个长度为1e5的数字.要想办法降幂. 我 ...

  8. 2016计蒜之道复赛A 百度地图的实时路况

    百度地图的实时路况功能相当强大,能方便出行的人们避开拥堵路段.一个地区的交通便捷程度就决定了该地区的拥堵情况.假设一个地区有 nnn 个观测点,编号从 111 到 nnn.定义 d(u,v,w)d(u ...

  9. 2016计蒜之道复赛 百度地图的实时路况 floyd+cdq分治

    链接:https://nanti.jisuanke.com/t/11217 奉上官方题解: 枚举 d(x , y , z) 中的 y,把 y 从这个图中删去,再求这时的全源最短路即可,使用 Floyd ...

随机推荐

  1. ubuntu中安装python3和pip

    python3: 在ubuntu的包中,python的二代和三代版本的命名:二代:python,三代:python3 安装python3: sudo apt install python3 同理:pi ...

  2. 自学Python编程的第三天----------来自苦逼的转行人

    2019-09-14 11:09:50 学Python的第三天和写博客的第三天 本来第三天的内容前天就应该发的,但是因为有点难度,用了两天的时间去学习,按道也是昨天发, 因为中秋导致今天早上发,第三天 ...

  3. 设计模式--Bulider模式

    起因:最近在做统计计算,创建的实体中属性比较多,都是一些数值,一开始是通过get.set方法进行赋值,占用了很多业务代码方法的长度,可读性不太好,后来改用了添加构造器的方式,稍显精简了一点,但是每次赋 ...

  4. 学习笔记之盘一盘 Python 系列 1 & 2 - 入门篇

    盘一盘 Python 系列 1 & 2 - 入门篇 https://mp.weixin.qq.com/s?__biz=MzIzMjY0MjE1MA==&mid=2247486473&a ...

  5. js删除对象里的某一个属性

    var a={"id":1,"name":"danlis"}; //添加属性 a.age=18; console.log(a); //结果: ...

  6. JWT生成token及过期处理方案

    业务场景 在前后分离场景下,越来越多的项目使用token作为接口的安全机制,APP端或者WEB端(使用VUE.REACTJS等构建)使用token与后端接口交互,以达到安全的目的.本文结合stacko ...

  7. python-pyhon与模块安装

    python 安装Python,配置环境变量,路径为python安装路径,如D:\pythoncmd中输入python可以识别则安装成功 pip升级指令python -m pip install -- ...

  8. 爬虫之scrapy框架应用selenium

    一.利用selenium 爬取 网易军事新闻 使用流程: ''' 在scrapy中使用selenium的编码流程: 1.在spider的构造方法中创建一个浏览器对象(作为当前spider的一个属性) ...

  9. 外部服务发现-ingress

    Ingress`其实就是从 kuberenets 集群外部访问集群的一个入口,将外部的请求转发到集群内不同的 Service 上,其实就相当于 nginx.haproxy 等负载均衡代理服务器,Ing ...

  10. springmvc手动获取bean

    @Service @Lazy(false) public class SpringContextHolder implements ApplicationContextAware, Disposabl ...