最新文章
这里会显示最新的几篇文章摘要。
记录生活,分享知识,与你一起成长。
这里会显示最新的几篇文章摘要。
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是≤50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
1行,若干个整数(≤100000),为导弹依次飞来的高度
2行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
389 207 155 300 299 170 158 65
6
2
题目有两点要求:
对于第一点,把数组倒过来,用lower_bound()算出最长递增子系列,就可以了,对于第二点,有一个什么定理,相当于计算原来数列最长上升子序列的长度,计算方法一样
int v[1000005];
int dp[1000005],f[1000005];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
//
// freopen("E:/Code/C++/untitled1/input.txt","r",stdin);
// freopen("output.txt","w",stdout);
mem(v);mem(dp);mem(f);//初始化
int t,cnt = 0;
while (cin >> t)
{
v[cnt++] = t;
}//cnt = size
//算第二点
f[1] = v[0];//边界,记录长度为1的子序列的最小末尾值
dp[0] = 1;//记录长度
int cnt_f = 1;//记录最大的子序列长度
for(int i = 0;i < cnt;++i)
{
auto h = lower_bound(f+1,f+cnt_f + 1,v[i])-(f+1);//使用二分查找找到v[i]比哪个长度的子序列末端大
f[h+1] = v[i];//更新子序列末端的值
if(h+1>cnt_f) cnt_f = h+1;//更新最大子序列长度
dp[i] = h+1;//de3(t,v[i],dp[i]);
}
int ans = cnt_f;
//算第一点
mem(f);mem(dp);
for(int i = 0;i < cnt/2;++i)
swap(v[i],v[cnt-i-1]);
cnt_f = 1;
dp[0] = 1;
f[1] = v[0];
for(int i = 1;i < cnt;++i)
{
auto h = lower_bound(f+1,f+cnt_f + 1,v[i]) - (f + 1);
f[h+1] = v[i];
if(h+1 > cnt_f) cnt_f = h+1;
dp[i] = h + 1;
}
cout << cnt_f << endl << ans;
}