#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
using namespace std;
#define For(a,begin,end) for(register int a=begin;a<end;a++)
int main()
{ //寻找最长的降序数列->我们只需要长度!!!
// freopen("1.in","r",stdin);!!!
vector <int> s,d,d2;
int n,h;
n=1;
while(cin>>h)//ctrl+z
{
n++;
s.push_back(h);
}
n--;
d.push_back(*s.begin());
d2.push_back(*s.begin());
//目的是找到一个最长的下降序列(准确->不上升)
//于是我们改变d[i]的定义-> i为长度时,最优的结尾元素->就是d[i]
//但是整个数列并不是最长的下降序列(虽然长度是对的 r:33-36)
For(i,1,n)
{
if(s[i]<=d.back())
d.push_back(s[i]);
else{
//使用upper_bound() 返回第一个大于查找值的指针 ,(升序数列)
//当我们加上 greater<int>() 时,返回第一个小于查找值的指针
//用s[i]替换这个值(因为s[i]比它大,因此我们可以在数组里储存更多的数字)
//这个操作导致我们的d[]就可能不是最长的下降序列了
//我们把比最小值大的数移到了它前面,但是呢又不改变其长度,又可以扩充其空间,
//使其之后可以容纳更多的数字->相当于数字之间更紧密了(往左看时)
/*某种往左靠的精准*/
*upper_bound(d.begin(),d.end(),s[i],greater<int>()) =s[i];
}
if(s[i]>d2.back())
d2.push_back(s[i]);
else{//lower_bound 找第一个>=ta的,然后换掉
*lower_bound(d2.begin(),d2.end(),s[i])=s[i];
}
}
cout<<d.size()<<"\n"<<d2.size();
return 0;
}
感觉dp优化到比较精妙的时候,似乎算法就有点像人类的思考方式一样了,不过计算机是一遍找完,而我们可能需要反复猜想论证,最终得出正确结果。
比如此题寻找最长的下降序列,如果我不是靠计算机解决这个问题的话,那么我也会尽量找到两个最接近的数在一起,因为这样就能存更多的数了,但是数一多起来就又做不下去了,因此上面的“替换”代码就很具有思考价值了。
描述
莱尼尔是海鲁拉大地之中最强的怪兽之一,无论近战还是远程攻击,莱尼尔都近乎完美。
莱尼尔最令人闻风丧胆的远程攻击是箭雨,这是一种能够动态跟踪对手所在位置的空对地攻击。无论距离多远,只要箭雨飞出,打击必达。
为了能够完美抵御莱尼尔的箭雨,约珥开发了一种箭雨拦截系统,可以发射出若干海鲁拉盾,在空中拦截莱尼而的箭雨。于此同时,整个拦截系统可以透过ambo的方式传送给林克。
但是每套箭雨拦截系统有一个缺陷:第一面地对空的发射的海鲁拉盾可以到达任意的高度,但是以后每一面海鲁拉盾都不能高于前一面的高度。
在实际战斗中,已知莱尼尔射出的箭雨阵中每一支雷电箭依次飞来的高度(高度数据是≤50000的正整数)。
请计算每套箭雨拦截系统最多能拦截多少支雷电箭?
如果要拦截所有雷电箭,林克最少要配备多少套这种雷电箭拦截系统?
输入
1行,若干个整数(个数≤100000)
注意:共有20组测试数据,前10组N^2算法可AC,后10组需要n(logn)算法。
输出
2行,每行一个整数。
第一个数字表示这套箭雨系统最多能拦截多少雷电箭。