标签:style blog http color os io for ar 2014
题意:给定一个序列,要求删去一个连续子序列后,得到的序列有一个最长的连续递增序列,输出最长连续递增序列长度
思路:先左右扫描一遍,把每个位置往左和往右的最大长度记录下来,然后在从左往右扫描一遍,开一个数组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[N], left[N], right[N], Min[N]; 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(扫描+二分)
标签:style blog http color os io for ar 2014
原文地址:http://blog.csdn.net/accelerator_/article/details/38819873