zoukankan      html  css  js  c++  java
  • [Jobdu] 题目1500:出操队形

    题目描述:

    在读高中的时候,每天早上学校都要组织全校的师生进行跑步来锻炼身体,每当出操令吹响时,大家就开始往楼下跑了,然后身高矮的排在队伍的前面,身高较高的就要排在队尾。突然,有一天出操负责人想了一个主意,想要变换一下队形,就是当大家都从楼上跑下来后,所有的学生都随机地占在一排,然后出操负责人从队伍中抽取出一部分学生,使得队伍中剩余的学生的身高从前往后看,是一个先升高后下降的“山峰”形状。据说这样的形状能够给大家带来好运,祝愿大家在学习的道路上勇攀高峰。(注,山峰只有一边也符合条件,如1,1、2,2、1均符合条件)

    输入:

    输入可能包含多个测试样例。
    对于每个测试案例,输入的第一行是一个整数n(1<=n<=1000000):代表将要输入的学生个数。
    输入的第二行包括n个整数:代表学生的身高(cm)(身高为不高于200的正整数)。

    输出:

    对应每个测试案例,输出需要抽出的最少学生人数。

    样例输入:
    6
    100 154 167 159 132 105
    5
    152 152 152 152 152
    样例输出:
    0
    4

    最长递增子序列问题的变型,从左找一遍,从右找一遍,再扫描一遍,找出dp1[i] + dp2[i]的最大值。最长递增子序列可以用二分查找优化成O(nlogn)的复杂度。手写了个二分找lower_bound的函数,也可以用STL里的。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <vector>
     4 #include <algorithm>
     5 using namespace std;
     6  
     7 int N;
     8 vector<int> v;
     9 vector<int> dp1, dp2;
    10 vector<int> st;
    11  
    12 void binSearch(int target) {
    13     if (st.empty() || target > st.back()) {
    14         st.push_back(target);
    15     } else {
    16         int l = 0, r = (int)st.size() - 1, m;
    17         while (l <= r) {
    18             m = l + ((r - l) >> 1);
    19             if (st[m] >= target) r = m - 1;
    20             else l = m + 1;
    21         }
    22         st[l] = target;
    23     }
    24 }
    25  
    26 void getDP() {
    27     st.clear();
    28     for (int i = 0; i < v.size(); ++i) {
    29         binSearch(v[i]);
    30         dp1[i] = st.size();
    31     }
    32     st.clear();
    33     for (int i = (int)v.size() - 1; i >= 0; --i) {
    34         binSearch(v[i]);
    35         dp2[i] = st.size();
    36     }
    37 }
    38  
    39 void solve() {
    40     getDP();
    41     int res = 0;
    42     for (int i = 0; i < N; ++i) {
    43         res = max(res, dp1[i] + dp2[i] - 1);
    44     }
    45     cout << N - res << endl;
    46 }
    47  
    48 int main() {
    49     while (scanf("%d", &N) != EOF) {
    50         v.resize(N);
    51         dp1.resize(N);
    52         dp2.resize(N);
    53         for (int i = 0; i < N; ++i) scanf("%d", &v[i]);
    54         solve();
    55     }
    56     return 0;
    57 }
    58 /**************************************************************
    59     Problem: 1500
    60     User: hupo250
    61     Language: C++
    62     Result: Accepted
    63     Time:1050 ms
    64     Memory:13244 kb
    65 ****************************************************************/
  • 相关阅读:
    数据库事务4种隔离级别及7种传播行为
    Spring AOP深入剖析
    SQL语句-创建索引
    global文件中的application_start方法中做: 定时器
    细说ASP.NET Forms身份认证
    asp.net(C#)实现功能强大的时间日期处理类完整实例
    C# 文件操作类大全
    SQL Server Profiler:使用方法和指标说明
    分库分表原则 总结
    做软件与团队建设——对带研发团队和管理的总结
  • 原文地址:https://www.cnblogs.com/easonliu/p/4461884.html
Copyright © 2011-2022 走看看