UVA - 1471 Defense Lines 神奇的解法

Description

Download as PDF

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 to the northern woods. Your advisors determined that the quality of the defense depended only on one factor: the length of a longest contiguous tower sequence of increasing heights. (They gave you a lengthy explanation, but the only thing you understood was that it had something to do with firing energy bolts at enemy forces).

After some hard negotiations, it appeared that building new towers is out of question. Mages of Ardenia have agreed to demolish some of their towers, though. You may demolish arbitrary number of towers, but the mages enforced one condition: these towers have to be consecutive.

For example, if the heights of towers were, respectively, 5, 3, 4, 9, 2, 8, 6, 7, 1, then by demolishing towers of heights 9, 2, and 8, the longest increasing sequence of consecutive towers is 3, 4, 6, 7.

Input 

The input contains several test cases. The first line of the input contains a positive integer  Z$ \le$25, denoting the number of test cases. Then  Z test cases follow, each conforming to the format described below.

The input instance consists of two lines. The first one contains one positive integer n$ \le$2 . 105 denoting the number of towers. The second line containsn positive integers not larger than 109 separated by single spaces being the heights of the towers.

Output 

For each test case, your program has to write an output conforming to the format described below.

You should output one line containing the length of a longest increasing sequence of consecutive towers, 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
题目大意就是给定一个序列 中间删除一些序列 求能得到的最大上升子序列长度。看书上的解释一大坨 自己试着写了写 TLE了 = = 又看了看 什么set什么好像很麻烦的样子 然后看到了int64b的代码 这位老兄一直代码风格简洁 思路清晰 于是我看了半个小时 才看懂究竟是怎么回事 他是用了一个数组Min 先求出左右递增的长度 (预处理) 然后枚举i Min[i]表示长度为i的递增序列 起始位置为Min[i] 这样一来 直接用lower_bound就可以找到起始位置小于当前i的位置了 再更新一下当前答案和Min中的值 恩 反正我觉得很神奇 因为他的代码显示是图片 所以贴我的好了 = = 跟他的稍稍有点不同 但是主要还是借鉴的他的思路 不得不说这个想法 太棒 = = 膜拜Orz
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 5;
int T,n,s[maxn],sum1[maxn],sum2[maxn],Min[maxn];//Min[i]:左延伸长度为i的序列起始位置为Min[i]
void init(){
        sum1[1]=1;
        for(int i=2;i<=n;i++)
        sum1[i]=s[i]>s[i-1]?sum1[i-1]+1:1;
        sum2[n]=1;
        for(int i=n-1;i>0;i--)
        sum2[i]=s[i]<s[i+1]?sum2[i+1]+1:1;
        return;
}
int main(){
    scanf("%d",&T);
    while(T--){
        memset(sum1,0,sizeof(sum1));
        memset(sum2,0,sizeof(sum2));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&s[i]);
        init();
        int ans=0;
        memset(Min,127,sizeof(Min));
        for(int i=1;i<=n;i++){
            int len=lower_bound(Min+1,Min+1+n,s[i])-Min-1;
            ans=max(ans,sum2[i]+len);
            Min[sum1[i]]=min(Min[sum1[i]],s[i]);
        }
        printf("%d\n",ans);
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值