您的位置:首页 > Web前端

UVA - 1471 Defense Lines 神奇的解法

2015-07-22 20:36 866 查看
Description





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

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

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
=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;
}


[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: