uva 1471

LIS变形,最后一个循环i是长度,d[i]存储的是相同长度最小的最后一个元素,也就是啊a[i],然后和

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn=200000+10;
int a[maxn],f[maxn],g[maxn];
int d[maxn];
const int inf=0x3f3f3f3f;
int t,n;
int main()
{
    scanf("%d",&t);
    while(t--)
    {    scanf("%d",&n);
        memset(d,inf,sizeof(d));
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
         f[1]=1;
         for(int i=2;i<=n;i++)
         {
             if(a[i]>a[i-1]) f[i]=f[i-1]+1;//上升到a[i]的最大长度
             else f[i]=1;
         }
         g[n]=1;
         for(int i=n-1;i>=1;i--)
         {
             if(a[i]<a[i+1])  g[i]=g[i+1]+1;//a[i]开始上升的最大长度
             else g[i]=1;
         }
         int ans=0;
         for(int i=1;i<=n;i++)
         {
             int len=lower_bound(d+1,d+1+i,a[i])-(d+1)+g[i];//g[i]对应a[i],要找到a[i]对应的f[i]
             ans=max(ans,len);
             d[f[i]]=min(d[f[i]],a[i]);//更新相同长度的最小a[i],让d[i]=它
         }
         printf("%d\n",ans);
    }
    return 0;
}

g[i]衔接

时间: 2024-08-05 15:46:22

uva 1471的相关文章

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

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

uva 1471 Defense Lines

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

uva 1471 Defense Lines (降低复杂度)

题意: 给一个长度为n(n <= 200000) 的序列,你删除一段连续的子序列,使得剩下的序列拼接起来,有一个最长的连续递增子序列 思路: 设f[i] 和g[i] 分别表示 以i为开始 和 以i为结束 的最长连续递增序列长度 首先可以想到枚举i和j,然后计算max_len = f[i] + g[i]; 但是这种枚举方法的时间复杂度是O(n^2),这是在加上预处理f[i] 和g[i] 的前提下 所以需要想一个更加优化的方法,避免那么多枚举: 所以想到 只枚举f[i], 通过某种方法快速的找到合适

【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≤

uva 1471 defence lines——yhx

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 fortication is a line of magetowers, starting near the city and continuing to t

UVa 1471 (LIS变形) Defense Lines

题意: 给出一个序列,删掉它的一个连续子序列(该子序列可以为空),使得剩下的序列有最长的连续严格递增子序列. 分析: 这个可以看作lrj的<训练指南>P62中讲到的LIS的O(nlogn)的优化变形过来的问题. 预处理: Li是第i个元素Ai向左延伸的最大长度,即[i, i + Li - 1]是一个递增区间 同样地,Ri是第i个元素向右延伸的最大长度. 我们,可以枚举i, j(j<i 且 Aj < Ai),这样就可以把Aj和Ai“拼接”起来,所得到的最长连续递增子列的长度就是Lj

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 防线

给一个长度为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 算法分析

难度:β+ 用时:0 min 题目:?? 代码:?? 这是一道贪心题. 然而不是一道简单的贪心题. 题目要求在一个大区间里删掉一个区间使得与该区间左右相邻的连续递增序列之和最长. 注意左右两侧的连续递增序列是合并后当作一整个看的. (解释不清还是看书吧) 这题可以用暴力,然而会 TLE. 暴力做法就是统计以 i 点结尾的最长序列长度 g(i) 和以 i 点开头的最长序列长度 f(i)(递增的). 然后枚举 i,j,答案是 max { g(i) + f(j) }.这样会超时. 正解算法是在这基础上