【二分】Defense Lines

[UVa1471] Defense Lines

算法入门经典第8章8-8 (P242)

题目大意:将一个序列删去一个连续子序列,问最长的严格上升子序列 (N<=200000)

试题分析:算法1:直接暴力,对于一个删除序列,枚举头和尾,然后看最长上升子序列。时间复杂度:O(N^3)

     算法2:L[i]表示以i为结尾的最长严格上升子序列长度,R[i]表示以i为开头的最长严格上升子序列长度。 预处理:O(N)

          然后依旧是枚举头和尾,那么答案就是L[i]+R[j]了。时间复杂度:O(N^2)

     算法3:第一个与第二个时间复杂度对于题目来说都非常之高,所以O(NlogN)是我们需要的。

          预处理是必须要的,这样能除以O(N)。

          下面要改进的就是这个枚举i,j的循环了,能不能确定j(i),来唯一确定最优的i(j)呢?

          到这里,性质就比较显然了,我们需要用一个数据结构来维护它。

          那么具体用什么呢?这就是单调队列的典型问题了。

          可以发现,如果a[i‘]>=a[i] , 且L(i‘)>=L(i),那么要i是没有用的,因为i‘更优或者余地更大了。

          然后维护这样一个数组,每次二分仅次于A[i]的值相加就好了。

          可能有些抽象,具体请看代码。

代码:

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;

#define LL long long

inline int read(){
	int x=0,f=1;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
	for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
	return x*f;
}
const int INF=2147483640;//注意a[i]<=1e9,要开大一点
const int MAXN=2000001;
int L[MAXN+1],R[MAXN+1];
int N; int T;
int a[MAXN+1]; int Que[MAXN+1];
int FLen; int ans;

int main(){
	T=read();
	while(T--){
		N=read();
		for(int i=1;i<=N;i++) a[i]=read();
		L[1]=1,R[N]=1;//预处理
		for(int i=2;i<=N;i++){
			L[i]=1;
			if(a[i]>a[i-1]) L[i]+=L[i-1];
		}
		for(int i=N-1;i>=1;i--){
			R[i]=1;
			if(a[i]<a[i+1]) R[i]+=R[i+1];
		}
		ans=0;
		for(int i=1;i<=N;i++) Que[i]=INF;
		for(int i=1;i<=N;i++){
			FLen=lower_bound(Que+1,Que+1+N,a[i])-Que;//二分第一个大于等于于a[i]的值
			ans=max(ans,FLen+R[i]-1);//计算长度,由于lower_bound是大于等于,所以要-1,让其变成第一个<a[i]
			Que[L[i]]=min(Que[L[i]],a[i]);//相同的最后如果越小,后面的潜力越大
		}
		printf("%d\n",ans);
	}
	return 0;
}

  

时间: 2024-10-01 06:48:16

【二分】Defense Lines的相关文章

UVA - 1471 Defense Lines 树状数组/二分

                              Defense Lines After the last war devastated your country, you - as the king of the land of Ardenia - decided it washigh time to improve the defense of your capital city. A part of your forti?cation is a line of magetower

UVA 1471 - Defense Lines(扫描+二分)

UVA 1471 - Defense Lines 题目链接 题意:给定一个序列,要求删去一个连续子序列后,得到的序列有一个最长的连续递增序列,输出最长连续递增序列长度 思路:先左右扫描一遍,把每个位置往左和往右的最大长度记录下来,然后在从左往右扫描一遍,开一个数组Min用来记录长度i的序列,最后一位的最小值,这个序列是满足单调性的,因为递增序列肯定是1,2,3,4...这样不断往上加的,如果遇到一个a[i]比较小的,就维护Min相应长度下的值,这样在这个单调递增的序列中,每次就可以二分找出最后一

1471 - Defense Lines(二分查找)

这道题非常巧妙,其中的思想很重要.. 题目要求删除一个连续子序列,将剩下的序列拼接起来之后问最长连续递增子序列的长度. 最长子序列的一个常见优化就是用一个数组保存到该点为止的连续子序列长度,但是对于本题来说这样的优化显然还是不够的因为n很大,二重循环还是会超时.所以我们可以只枚举一个量,但是另一个量怎么找呢, 答案是构造一个二元组,a和g,使这两个元素都严格递增.这样我们在枚举一个i时只要二分找到第一个比a[i]小的值,他对应的那个g也是最大的. 然后问题的关键就在与对集合的操作,说白了就是构造

1471 - Defense Lines

After the last war devastated your country, you - as the king of the land of Ardenia - decided it was high time to improve the defense of your capital city. A part of your fortification is a line of mage towers, starting near the city and continuing

【uva 1471】Defense Lines(算法效率--使用数据结构)

题意:给一个长度为N(N≤200000)的序列,要删除一个连续子序列,使得剩下的序列中有一个长度最大的连续递增子序列,输出其长度. 解法:(参考自紫书)1.X 暴力枚举删除的区间 [l,r],O(n^2),再数需要O(n).总共O(n^3). 2.X 前者+O(n)预处理 f[i] 和 g[i] 表示前缀和后缀的长度最大的连续递增子序列长度.总共O(n^2). 3.√ 前者O(n)预处理+ 只枚举 r(部分枚举),快速找最优的 l.而最优的就是 Ai 尽量小而f[i]尽量大,就可以排除掉 Ai≤

UVa1471 Defense Lines (滑动窗口)

链接:http://bak.vjudge.net/problem/UVA-1471 分析:设g(i)为以第i个元素结尾的最长L序列长度,f(i)为以第i个元素开头的最长L序列长度,首先在O(n)时间内求出f(i)和g(i),枚举完j和i之后,最长L序列的长度就是g(j)+f(i)|j<i,A[j]<A[i]. 这样做的时间复杂度是O(n²).还可以优化的更好,只枚举i,不枚举j,使用STL中的set,set容器可以看成是排好序的,而且自带lower_bound和upper_bound函数,把所

UVA 1471 Defense Lines 防线

给一个长度为n的序列,要求删除一个连续子序列,使剩下的序列有一个长度最大的连续递增子序列. 最简单的想法是枚举起点j和终点i,然后数一数,分别向前或向后能延伸的最长长度,记为g(i)和f(i).可以先预处理出每一个点能往前和往后延伸的长度(g(i)和f(i)).然后枚举终点j,快速找一个g(j)最大的起点.如果有两个候选的起点,一个j,一个j‘,A[j']<=A[j]且g[j']>g[j],那么j一定可以排除,g(j')更大,而且更容易拼接. 固定i的情况下,所有有价值的(A[j],g(j))

UVA - 1471 Defense Lines (set/bit/lis)

紫薯例题+1. 题意:给你一个长度为n(n<=200000)的序列a[n],求删除一个连续子序列后的可能的最长连续上升子序列的长度. 首先对序列进行分段,每一段连续的子序列的元素递增,设L[i]为下标i对应的元素向左能延伸到的最大长度(在同一段内),R[i]为向右能延伸到的最大长度,则问题转化成了对于每个下标i,找到在它前面的下标j中a[j]<a[i]且L[j]最大的j,然后用R[i]+L[j]去更新ans. 第一种方法是用一个二元组(x,y)表示大小为x的元素所对应的L的值,用一个set保存

uva 1471 Defense Lines

题意: 给一个长度为n(n <= 200000) 的序列,你删除一段连续的子序列,使得剩下的序列拼接起来,有一个最长的连续递增子序列 分析: 就是最长上升子序列的变形.需要加一个类似二分搜索就好. 代码: #include <iostream>#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int maxn=200005;const int