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,sizeof(a))

using namespace std;

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

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

int main()
{
    freopen("in.txt","r",stdin);
    int T;cin>>T;
    while(T--){
        scanf("%d",&n);
        REP(i,1,n) scanf("%d",&a[i]);
        if(n==0){
            cout<<0<<endl;
            continue;
        }
        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;
        //cout<<n<<endl;REP(i,1,n) cout<<a[i]<<" ";cout<<endl;
        //REP(i,1,n) cout<<f[i]<<" ";cout<<endl;
        //REP(i,1,n) cout<<g[i]<<" ";cout<<endl;
        int ans=1;
        q[len=1]={a[1],g[1]};
        REP(i,2,n){
            Node cur={a[i],g[i]};
            if(cur.x>q[len].x){
                ans=max(ans,f[i]+q[len].y);
                if(cur.y>q[len].y) q[++len]=cur;
            }
            else{
                int k=lower_bound(q+1,q+len+1,cur)-q;
                if(k>1) ans=max(q[k-1].y+f[i],ans);
                else ans=max(ans,f[i]);
                if(cur.x==q[k].x&&cur.y<q[k].y) continue;
                if(cur.x<q[k].x&&cur.y<q[k].y) continue;
                q[k]=cur;
            }
            //cout<<i<<" "<<ans<<endl;
        }
        cout<<ans<<endl;
    }
    return 0;
}
/**
题意:
给定一个长度为n的序列,求随便去掉一段后(可以不去),序列的最长连续递增子序列长度。
这题我先按紫书上的思路写的,那个思路的正确性是显然的,但是需要用set,在这种二元组中
用set是非常恶心的,很容易出错,因此我写挂了。后来换了另一种思路,直接按照lis的
写法,调了一下细节就过了。

思路:
先分别预处理出以a[i]为开头和结尾的连续子序列长度f[i]和g[i],
接着按照基本的思路,枚举f[i],快速找到符合条件且最优的g[j],然后更新答案,将a[i],g[i]添加进去。
由于无法划窗,快速找到g[i]就二分了,那么这个时候自然就会想到lis的nlogn算法,更新状态直接替代就行了。
如何二分呢?当然是要看符合的条件和最优的单调性了,符合条件是指a[j]<a[i],最优就是
在符合条件的前提下使得g[i]尽可能大。
这里需要保持lis的单调性,如何保持单调性呢?这个思考过程我使用分类讨论的(智商太低无法一眼看出),
二分找到第一个>=cur的q[k],根据a和g的大小关系总共6种情况(等于也算),以此来确定是否应该用cur将k替换。

*/
View Code

 

posted @ 2015-12-10 16:24  __560  阅读(320)  评论(0编辑  收藏  举报