UVA 1471 Defense Lines (STL + 二分)
大体题意:
给你一个长度为n(n < 2e5)的序列,你的任务是删除一个连续的子序列,使得剩下的序列中有一个长度最大的连续递增子序列。求最大序列长度?
思路:
因为要删除一个连续的子序列,所以会分成左右两部分之和的形式,我们枚举右边一部分的起点位置i,快速的找到左边一个合适的位置j,使得a[j] < a[i] 并且 g[j]尽量大。
(注: g[i]表示以i 位置结束的最长上升连续子序列的长度,f[i]表示以i位置开始的最长上升连续子序列的长度)
这样我们可以利用set 来维护当前合法的左边位置的值。
什么是合法的? 必须是a[i] > a[j] 并且 g[i] > g[j], 这样我们可以按照a[i]排序,那么g[i]也一定是升序的,
这样我们加入一个 就删除不合法的。
利用set里的二分查找lower_bound 便很快的查到合法的位置了。
详细见代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#define Max(a,b)((a)<(b)?(b):(a))
using namespace std;const int maxn = 2e5 + 10;int T, n;
int g[maxn], f[maxn], a[maxn];struct Node{int id;int len;Node(int id = 0,int len = 0):id(id),len(len){}bool operator < (const Node& rhs) const {return a[id] < a[rhs.id] || (a[id] == a[rhs.id ] && len < rhs.len);}bool operator == (const Node & rhs) const {return id == rhs.id && len == rhs.len;}
};set<Node>s;
set<Node>::iterator it,it2,it3;int main(){scanf("%d",&T);while(T--){scanf("%d",&n);s.clear();for (int i = 1; i <= n; ++i)scanf("%d",a+i);g[1] = 1;for (int i = 2; i <= n; ++i){if (a[i] > a[i-1]){g[i] = g[i-1] + 1;}else g[i] = 1;}f[n] = 1;for (int i = n-1; i >= 1; --i){if (a[i] < a[i+1] ) f[i] = f[i+1] + 1;else f[i] = 1;}int ans = 1;for (int i = 1; i <= n; ++i)ans = Max(ans,f[i]);s.insert(Node(1,1));for (int i = 2; i <= n; ++i){Node v = Node(i,g[i]);it = s.lower_bound(v);if (it != s.begin()){--it;Node u = *it;ans = Max(ans,u.len + f[i]);++it;}--it;s.insert(v);it = s.find(v);it2 = it;if (it2 != s.begin()){--it2;Node u = *it2;if (a[u.id] <= a[v.id]){if (u.len>= v.len) {s.erase(it);continue;}}}it2 = it;++it2;for ( ;it2 != s.end(); ){Node u = *it2;if (a[u.id] >= a[v.id]){if (u.len <= v.len) it2 = s.erase(it2);else break;;}}}printf("%d\n",ans);}return 0;
}
/**
2
9
5 3 4 9 2 8 6 7 1
7
1 2 3 10 4 5 6**/
UVA 1471 Defense Lines (STL + 二分)相关推荐
- UVA - 1471 Defense Lines 贪心+二分
题目大意:给出长度为n的序列,要求你删除掉一段的连续子序列,使得剩下的序列的递增子序列最长 解题思路:记录以下每个位置的值所能延伸的最左端和最右端,用一个数组记录长度为i的数的最小值,然后从左往右扫描 ...
- uva 1471 Defense Lines
题目大意:给定一串数字序列,然后叫你删除连续一部分序列,然后使得剩下的序列中存在的连续的最大增长序列长度是多少 . . // // main.cpp // uva UVa1471 Defense Li ...
- UVa 1471 Defense Lines - 线段树 - 离散化
题意是说给一个序列,删掉其中一段连续的子序列(貌似可以为空),使得新的序列中最长的连续递增子序列最长. 网上似乎最多的做法是二分查找优化,然而不会,只会值域线段树和离散化... 先预处理出所有的点所能 ...
- UVA 1471 Defense Lines 防线 (LIS变形)
给一个长度为n的序列,要求删除一个连续子序列,使剩下的序列有一个长度最大的连续递增子序列. 最简单的想法是枚举起点j和终点i,然后数一数,分别向前或向后能延伸的最长长度,记为g(i)和f(i).可以先 ...
- uva 1471 Defense Lines (降低复杂度)
题意: 给一个长度为n(n <= 200000) 的序列,你删除一段连续的子序列,使得剩下的序列拼接起来,有一个最长的连续递增子序列 思路: 设f[i] 和g[i] 分别表示 以i为开始 和 以 ...
- uva 1471 Defense Lines
题目:https://vjudge.net/problem/UVA-1471 题意: lrj思路:第一思路可以暴力枚举,先枚举i(i=1:len),i往右数,看以i开头的最大升序序列个数.然后再枚举 ...
- UVA 1471 Defense Lines (LIS变形)
题意:删除原序列中的一段连续子序列,使得剩下的序列中存在一段最长连续子序列. 题解:LIS变形 我们用l[i]l[i]l[i]和r[i]r[i]r[i]记录往右以iii结尾和往左以iii开头的最长连续 ...
- UVA 1471 Defense Lines 防线
https://vjudge.net/problem/UVA-1471 给一个长度为n的序列,要求删除一个连续子序列,使剩下的序列有一个长度最大的连续递增子序列. 例如 Sample Input 2 ...
- UVa 1471 Defense Lines (解释紫书思路)
题目链接:https://cn.vjudge.net/problem/UVA-1471 设序列L表示连续递增子序列: 则最长的L就可以分为两部分,一部分是以j结尾的序列,另一部分是以i为开头的序列 现 ...
最新文章
- docker虚拟机动态扩展内存
- 软件工程师的发明家—从发明家的视角分析软件
- php html转dom,PHP解析html类库simple_html_dom的转码bug
- Planetary Science and Life in the Universe
- Altium Designer -- PCB设置板框
- Docker_基础知识
- C++基本概念复习之二:多重继承、虚继承、纯虚函数(抽象类)
- php静态地图api,静态图API | 百度地图API SDK
- UNIX标准化及实现之POSIX标准可选头文件
- 大龄程序员想转产品经理?3本书给你最靠谱的进阶攻略
- PicoDet的学习笔记
- 大文件上传NeatUpload简单用法
- 《Redis设计与实现》读书笔记
- [境内法规]中国人民银行关于印发《反洗钱现场检查管理办法(试行)》的通知—银发〔2007〕175号
- 实验6 Matlab数值计算
- 循序渐进ActiveMQ(6)----使用zookeeper实现activemq的主从环境搭建
- 【19】processing-硬件(中文)
- Redis 的发布和订阅
- 第十三届蓝桥杯大赛软件赛省赛第二场(Java 大学A组)
- 开源社区那些事|社区分享
热门文章
- UE、UI、 IA和IxD傻傻分不清
- 「镁客·请讲」Video++董慧智:让AI融入消费级视频,我们打开了视频的“黑盒子”...
- 小程序导出数据到excel表,借助云开发后台实现excel数据的保存
- JAVA continue 用法
- 两个实打实干活的同事离职了,老板连谈都没谈,一句挽留都没有,你怎么看?
- 纯CSS边框渐变动画
- 仅仅有人物没背景的图片怎么弄_只会画人物不会画背景?这3种方法教你快速画背景!...
- StatusBarUtil 状态栏工具类(实现沉浸式状态栏/变色状态栏)
- 计算机术语中分辨率是什么意思,分辨率是什么?分辨率是什么意思?
- 现代OpenGL教程 02 - 贴图