导弹的召唤!!!

来源:互联网 发布:python 移除文件夹 编辑:程序博客网 时间:2024/06/10 23:34

实在是太TM中二了
果然又出现了新的玄学!!!!!!!!!!
题目背景

易琢然今天玩使命召唤,被敌军用空对地导弹轰炸,很不爽;众所周知,易琢然很不老实,他开了外挂;

外挂第一次可以打掉任意高度的导弹,之后每一次都不能打掉大于上一次高度的导弹;

但易琢然水平太差,敌军最多有300000颗导弹,导弹只能按顺序打,因为外挂有BUG,而且是超音速导弹,只有一秒导弹就到了,只能编程解决;

但易琢然上课不认真,平时帮他的sxy又不在,所以他只能求助于你
(第一次玄学的AC啦,不懂为啥!)
这个题目的数据跟上一道题导弹拦截比起来简直丧心病狂!
30000+导弹,早就炸平了吧233

上个题目的dp做法复杂度是n^2级别的,显然不可能AC(别问我为啥不用贪心)
忽然发现了一个比较强的东西,也就是最长上升子序列的 nlogn方法
于是学习了一下

我们定义一个数组
叫 rise
定义rise[i]是长度为i的最小的序列末尾的数!
我们在H数组中找一个最长上升子序列
len为当前序列长度!
定义rise[1]=H[1]
枚举H[2]-H[N]这些数
如果H[i]>rise[len],那么就把这个数放进序列
如果上面的条件不满足,我们就在序列中找一个序列中比该元素大的最小元素,将其修改成该元素
问题来了,为神魔要折磨做呢!!!
问的好!
其实其中有一点贪心的思想
由于这是一个最长上升子序列,那么前面的数不就是应该是越小越好吗?
懂吧!!!(其实讲的一点都不明白233)
OK,其余的啥子序列啊,类比着来就行了!
有了这个我们就可以过这个题了,第一层的N是不可避免的,由于是二分查找,复杂度是logN
这样的复杂度就是O(nlogn)啦!比某O(n^2)不知道好到哪去了!
第一问求最大不上升子序列,第二问求最大下降子序列
第一问找不到相应的STL函数,只好自己写个二分了
第二问lower_bound函数可以很好地满足我们的要求,所以用这个,方便!!!

#include <cstdio>#include <iostream>#include <algorithm>using namespace std;int h[300001],rise[300001],down[300001];int find(int l,int r,int x){    while(l<=r)    {     int mid=(r+l)/2;     if(down[mid]>=x)      l=mid+1;     else r=mid-1;    }    return l;}int main() {    int t=0;    int x;    while(scanf("%d",&x)!=EOF)     h[++t]=x;    int cnt=1;    down[1]=h[1];    for(int i=2;i<=t;i++)     if(h[i]<=down[cnt])      {        down[++cnt]=h[i];      }     else      {        down[find(1,cnt,h[i])]=h[i];      }    printf("%d\n",cnt);    cnt=1;    rise[1]=h[1];    for(int i=2;i<=t;i++)     if(h[i]>rise[cnt])      {        rise[++cnt]=h[i];      }     else      {        int poi=lower_bound(rise+1,rise+cnt+1,h[i])-rise;        rise[poi]=h[i];      }     printf("%d",cnt);     return 0;}
原创粉丝点击