uva1471 Defense Lines

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizoef(a))

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=1<<29;

int a[maxn],n;
int f[maxn],g[maxn];
struct Node
{
    int a,g;
    friend bool operator<(Node A,Node B)
    {
        return A.a<B.a;
    }
};

int main()
{
    freopen("in.txt","r",stdin);
    int T;cin>>T;
    while(T--){
        scanf("%d",&n);
        REP(i,1,n) scanf("%d",&a[i]);
        g[1]=1;
        REP(i,2,n) g[i]=a[i]>a[i-1]?g[i-1]+1:1;
        f[n]=1;
        for(int i=n-1;i>=1;i--) f[i]=a[i]<a[i+1]?f[i+1]+1:1;
        int ans=1;
        set<Node> s;
        s.insert({a[1],g[1]});
        bool can;
        REP(i,2,n){
            Node t={a[i],g[i]};
            //cout<<"i="<<i<<" a="<<a[i]<<" g="<<g[i]<<" f="<<f[i]<<endl;
            //for(set<Node>::iterator it=s.begin();it!=s.end();++it) cout<<(it->a)<<" "<<(it->g)<<endl; cout<<endl;
            set<Node>::iterator it=s.lower_bound(t);/// 找到第一个>=t的*it,然后判断能否插入
            //out<<(it->a)<<" -"<<(it->g)<<endl;
            if(it==s.begin()){
                if(it->a==a[i]){
                    if(it->g>=g[i]) can=0;
                    else can=1;
                }
                else can=1;
            }
            else{
                if(it->a==a[i]){
                    if(it->g>=g[i]) can=0;
                    else can=1;
                }
                else{ ///  判断前一个确定能否插入
                    set<Node>::iterator it1=it;--it1;
                    if(it1->g>=g[i]) can=0;
                    else can=1;
                }
            }
            if(can){
                bool flag=0;
                while(it!=s.end()){
                    if(flag) break;
                    if(it->a==a[i]){
                        set<Node>::iterator it1=it;++it1;
                        s.erase(it);
                        it=it1;
                    }
                    else{
                        set<Node>::iterator it1=it;++it1;
                        if(it->g<=g[i]) s.erase(it),it=it1;
                        else flag=1;
                    }
                }

            }
            int tmp;
            if(it==s.begin()) tmp=f[i];
            else tmp=(--it)->g+f[i];
            //cout<<(it->a)<<" "<<(it->g)<<"=="<<endl;
            ans=max(ans,tmp);
            //cout<<"tmp="<<tmp<<endl;
            //if(tmp==5) cout<<"i="<<i<<" f[i]="<<f[i]<<" a="<<(it->a)<<" g="<<(it->g)<<" g[i]="<<g[i]<<endl;
            s.insert(t);
            //for(set<Node>::iterator it=s.begin();it!=s.end();++it) cout<<(it->a)<<"_"<<(it->g)<<endl; cout<<endl;
        }
        cout<<ans<<endl;
    }
    return 0;
}

/**
用set维护的经典题。
单调栈,单调队列,set,,,思维方式很像。
*/

居然又WA了。。。

时间: 2024-10-14 00:39:53

uva1471 Defense Lines的相关文章

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函数,把所

【二分】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:第

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

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) 的序列,你删除一段连续的子序列,使得剩下的序列拼接起来,有一个最长的连续递增子序列 分析: 就是最长上升子序列的变形.需要加一个类似二分搜索就好. 代码: #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≤

UVALive 4976 Defense Lines ——(LIS变形)

题意:给出序列,能够从这序列中删去连续的一段,问剩下的序列中的最长的严格上升子串的长度是多少. 这题颇有点LIS的味道.因为具体做法就是维护一个单调的集合,然后xjbg一下即可.具体的见代码吧: 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 using namespace std; 5 const int N = 2e5 + 5; 6 7 int T,n,top,back; 8 i