1471 - Defense Lines

After the last wardevastated your country, you - as the king of the land of Armenian - decided itwas high time to improve the defense of your capital city. A part of yourfortification is a line of mage towers, starting near the city and continuingto the northern woods. Your advisors determined that the quality of the defensedepended only on one factor: the length of a longest contiguous tower sequenceof increasing heights. (They gave you a lengthy explanation, but the only thingyou understood was that it had something to do with firing energy bolts atenemy forces).

After some hard negotiations,it appeared that building new towers is out of question. Mages of Armenian haveagreed to demolish some of their towers, though. You may demolish arbitrarynumber of towers, but the mages enforced one condition: these towers have to beconsecutive.

For example, ifthe heights of towers were, respectively, 5, 3, 4, 9, 2, 8, 6, 7, 1, then bydemolishing towers of heights 9, 2, and 8, the longest increasing sequence ofconsecutive towers is 3, 4, 6, 7.

Input 

The input containsseveral test cases. The first line of the input contains a positive integer Z25, denoting the number oftest cases. Then Z test cases follow, each conforming to theformat described below.

The input instanceconsists of two lines. The first one contains one positive integer n2 .105 denotingthe number of towers. The second line contains n positiveintegers not larger than 109 separated by single spacesbeing the heights of the towers.

Output 

For each testcase, your program has to write an output conforming to the format describedbelow.

You should outputone line containing the length of a longest increasing sequence of consecutivetowers, achievable by demolishing some consecutive towers or no tower at all.

Sample Input 

2

9

5 3 4 9 2 8 6 7 1

7

1 2 3 10 4 5 6

Output 

4

6

代码:

#include<cstdio>

#include<set>

#include<cassert>

using namespacestd;

 

const int maxn =200000 + 5;

int n, a[maxn],f[maxn], g[maxn];

 

struct Candidate

{

    int a, g;

    Candidate(int a, int g):a(a),g(g) {}

    bool operator < (const Candidate& rhs)const

    {

        return a < rhs.a;

    }

};

 

set<Candidate>s;

 

int main()

{

    int T;

    scanf("%d", &T);

    while(T--)

    {

        scanf("%d", &n);

        for(int i = 0; i < n; i++)

        {

            scanf("%d", &a[i]);

        }

        if(n == 1)

        {

            printf("1\n");

            continue;

        }

//g[i] is thelength of longest increasing continuous subsequence ending at i

        g[0] = 1;

        for(int i = 1; i < n; i++)

        {

            if(a[i-1] < a[i])

            {

                g[i] = g[i-1] + 1;

            }

            else

            {

                g[i] = 1;

            }

        }

//f[i] is thelength of longest increasing continuous subsequence starting from i

        f[n-1] = 1;

        for(int i = n-2; i >= 0; i--)

        {

            if(a[i] < a[i+1])

            {

                f[i] = f[i+1] + 1;

            }

            else

            {

                f[i] = 1;

            }

        }

        s.clear();

        s.insert(Candidate(a[0], g[0]));

        int ans = 1;

        for(int i = 1; i < n; i++)

        {

            Candidate c(a[i], g[i]);

            set<Candidate>::iterator it =s.lower_bound(c); // first one that is >= c

            bool keep = true;

            if(it != s.begin())

            {

                Candidate last = *(--it); //(--it) points to the largest one that is < c

                int len = f[i] + last.g;

                ans = max(ans, len);

                if(c.g <= last.g)

                {

                    keep = false;

                }

            }

            if(keep)

            {

                s.erase(c);// if c.a is alreadypresent, the old g must be <= c.g

                s.insert(c);

                it = s.find(c);  //this is a bit cumbersome and slow but it'sclear

                it++;

                while(it != s.end() &&it->a > c.a && it->g <= c.g)

                {

                    s.erase(it++);

                }

            }

        }

        printf("%d\n", ans);

    }

    return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值