3 solutions
-
5
解析见代码
/*先讲一下思路: 本题来源于Noip1999(启蒙域A1260) 原题可以用O(n^2)算法过,但本题需要用O(nlogn) 原本的动态规划算法显然是不够的 最多能拦截几枚导弹,本质上就是一个最长不上升序列的长度(反正只有一套)(不一定连续) 需要配备几套系统,本质上就是一个最长上升序列的长度(高出去的要重新配备一套) 理论存在,实践开始! */ #include <bits/stdc++.h> using namespace std; const int N = 100010; int f[N]; //f数组存储的是最长不上升序列(注意不是子序列) int g[N]; //g数组存储的是最长上升序列(注意不是子序列) int h[N]; //h数组存储导弹的高度 int n;//n纯粹一个过程量,循环输入用的,可以优化 int main() { while (cin >> h[++ n]);//这里之所以使用++n而非n++,是因为n要从1开始(当然如果你初始化n=1,那么就用n++) n--; int res = 1, cnt = 1;//res和cnt的用法一致,只不过为区分用处,所以用了不同的名字 f[1] = g[1] = h[1];//初始化 for (int i = 2; i <= n; i ++ ) {//请注意,因为前面已经有一步n--的操作,所以这里的n实质上是n-1,由于已经初始化f,g,h数组的第一项一致,所以只需要从2开始 if (h[i] <= f[res]) f[++ res] = h[i];//若出现不大于(即不上升子序列的下一项)则自动补入 else{ int k = upper_bound(f + 1, f + res + 1, h[i], greater<int>()) - f; /*如果导弹的高度已经超出范围,那么就在已求出范围用upper_bound函数寻找 第一个<高度的,选择拦截更高的导弹,从而给出更大限度的发挥空间*/ f[k] = h[i];//根据地址锁定 } if (h[i] > g[cnt]) g[++ cnt] = h[i];//g数组同理,只不过加不加greater看情况 else{ int k = lower_bound(g + 1, g + cnt + 1, h[i]) - g; g[k] = h[i]; } } printf("%d\n%d\n", res, cnt);//输出 return 0; } //代码来自CSDN,注释是本人写的 /*附加样例分析: 第一步,先统一第1项高度为h[1]=389 第二步,满足207<=389(即f[1]),故f[2](即f[++1])=207,res=2; 不满足207>389,查找后得k=1,207替换389; 第三步,满足155<=207,故f[3]=155,res=3; 不满足155>207,查找后得k=1,155替换207; 第四步,不满足300>=155,查找后得k=2,300替换207; 满足300>155,cnt=2 …… 以此类推, 得res=6,拦截的6枚分别为389,300,299,170,158,65 cnt=2,需要配备初始射程为389,300的两套发射系统 */
Information
- ID
- 20
- Time
- 1000ms
- Memory
- 128MiB
- Difficulty
- 3
- Tags
- # Submissions
- 174
- Accepted
- 31
- Uploaded By