UVA 1471 - Defense Lines(扫描+二分)
2014-08-25 14:04
465 查看
UVA 1471 - Defense Lines
题目链接题意:给定一个序列,要求删去一个连续子序列后,得到的序列有一个最长的连续递增序列,输出最长连续递增序列长度
思路:先左右扫描一遍,把每个位置往左和往右的最大长度记录下来,然后在从左往右扫描一遍,开一个数组Min用来记录长度i的序列,最后一位的最小值,这个序列是满足单调性的,因为递增序列肯定是1,2,3,4...这样不断往上加的,如果遇到一个a[i]比较小的,就维护Min相应长度下的值,这样在这个单调递增的序列中,每次就可以二分找出最后一位小于a[i],然后和当前位置往右的序列长度拼接起来,得到一个长度,记录下最大值就是答案
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 200005;
int t, n, a
, left
, right
, Min
;
void init() {
scanf("%d", &n);
left[0] = 1; right[n - 1] = 1;
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
if (i) {
left[i] = 1;
if (a[i] > a[i - 1]) left[i] += left[i - 1];
}
}
for (int i = n - 2; i >= 0; i--) {
right[i] = 1;
if (a[i] < a[i + 1]) right[i] += right[i + 1];
}
}
int solve() {
int ans = 0;
memset(Min, INF, sizeof(Min));
for (int i = 0; i < n; i++) {
int len = lower_bound(Min + 1, Min + 1 + n, a[i]) - Min;
ans = max(ans, right[i] + len - 1);
Min[left[i]] = min(Min[left[i]], a[i]);
}
return ans;
}
int main() {
scanf("%d", &t);
while (t--) {
init();
printf("%d\n", solve());
}
return 0;
}
相关文章推荐
- UVA 1471 Defense Lines (STL + 二分)
- UVA - 1471 Defense Lines 贪心+二分
- UVa 1471 Defense Lines (二分+set优化)
- UVA - 1471 Defense Lines
- UVa1471 Defense Lines (贪心+思维+初学lower_bound())
- UVA - 1471 Defense Lines 神奇的解法
- 例题8-8 防线(Defense Lines, ACM/ICPC CERC 2010, UVa1471)
- uva 1471 - Defense Lines (最长上升子序列变形)
- UVa 1471 Defense Lines - 线段树 - 离散化
- UVa OJ 1471 - Defense Lines
- uva 1471 Defense Lines
- UVA - 1471 Defense Lines 树状数组/二分
- uva 1471 Defense Lines
- uva1471 - Defense Lines (最长上升子序列变形)
- UVa 1471 (LIS变形) Defense Lines
- UVA 1471 Defense Lines(set维护二元组单调队列)
- [是用数据结构]UVa1471 - Defense Lines
- 1471 - Defense Lines(二分查找)
- [算法竞赛入门经典] UVA 1471 - Defense Lines
- UVa1471 - Defense Lines