zoukankan      html  css  js  c++  java
  • JZOJ 3463. 【NOIP2013模拟联考5】军训

    Description

    HYSBZ 开学了!今年HYSBZ 有n 个男生来上学,学号为1…n,每个学生都必须参加军训。在这种比较堕落的学校里,每个男生都会有Gi 个女朋友,而且每个人都会有一个欠扁值Hi。学校为了保证军训时教官不会因为学生们都是人生赢家或者是太欠扁而发生打架事故,所以要把学生们分班,并做出了如下要求:

    1.分班必须按照学号顺序来,即不能在一个班上出现学号不连续的情况。

    2.每个学生必须要被分到某个班上。

    3.每个班的欠扁值定义为该班中欠扁值最高的那名同学的欠扁值。所有班的欠扁值之和不得超过Limit。

    4.每个班的女友指数定义为该班中所有同学的女友数量之和。在满足条件1、2、3 的情况下,分班应使得女友指数最高的那个班的女友指数最小。

    请你帮HYSBZ 的教务处完成分班工作,并输出女友指数最高的班级的女友指数。

    输入数据保证题目有解。
     

    Input

    第一行仅2 个正整数n, Limit,分别为学生数量和欠扁值之和的上限。

    接下来n 行每行2 个正整数Hi,Gi,分别为学号为i 的学生的欠扁值和女友数。

    Output

    仅1 个正整数,表示满足分班的条件下女友指数最高的班级的女友指数。
     

    Sample Input

    4 6
    4 3
    3 5
    2 2
    2 4

    Sample Output

    8
    【样例解释】
    分班按照(1,2),(3,4)进行,这时班级欠扁值之和为4+2=6<=Limit,而女友指数最高的班级为(1,2),为8。容易看出该分班方案可得到最佳答案。
     
     
    做法:我们可以二分最大的女友指数最小时为多少,可以设f[i]表示i 开头的班级的欠扁值之和
    优化见代码。
     
    代码如下:
     1 #include <cstdio>
     2 #include <iostream>
     3 #include <string>
     4 #include <cstring>
     5 #define LL long long
     6 #define N 20007
     7 using namespace std;
     8 LL n, limit, h[N], g[N], sum[N], num[N], z[N], ans, mid, f[N];
     9 int next[N];
    10 
    11 LL get(int t)
    12 {
    13     LL tl = t, tr = n;
    14     while (tl < tr)
    15     {
    16         LL mi = (tl + tr) / 2;
    17         if (sum[mi] - sum[t - 1] >= mid) tr = mi;
    18         else tl = mi + 1;
    19     }
    20     return tl;
    21 }
    22 
    23 bool check()
    24 {
    25     memset(f, 0x7f7f7f7f, sizeof(f));
    26     f[1] = 0;
    27     for (int i = 1; i <= n; i++)
    28     {
    29         int k = get(i);
    30         int x = i;
    31         int ma = h[i];
    32         if (sum[k] - sum[i - 1] > mid)    k--;
    33         while (x <= k)
    34         {
    35             f[x] = min(f[x], f[i] + ma);
    36             ma = h[x];
    37             x = next[x];
    38         }
    39         f[k + 1] = min(f[k + 1], f[i] + ma);
    40     }
    41     if (f[n + 1] <= limit)    return 1;
    42     return 0;
    43 }
    44 
    45 int main()
    46 {
    47     scanf("%lld%lld", &n, &limit);
    48     for (int i = 1; i <= n; i++)
    49     {
    50         scanf("%lld%lld", &h[i], &g[i]);
    51         sum[i] = sum[i - 1] + g[i];
    52     }
    53     int tail = 1;
    54     z[1] = 1e9 + 7;
    55     num[1] = n + 1;
    56     for (int i = n; i >= 1; i--)
    57     {
    58         while (h[i] >= z[tail])    tail--;
    59         next[i] = num[tail];
    60         tail++;
    61         z[tail] = h[i];
    62         num[tail] = i;
    63     }
    64     ans = sum[n];
    65     LL tl = 1, tr = ans;
    66     while (tl < tr)
    67     {
    68         mid = (tl + tr) / 2;
    69         if (check())    
    70         {
    71             if (mid < ans)    ans = mid;
    72             tr = mid;
    73         }
    74         else  tl = mid + 1;    
    75     }
    76     printf("%lld", tl);
    77 }
    View Code
  • 相关阅读:
    PyMySQL学习笔记
    Python 操作csv和excel表格
    Python爬虫之解析网页
    Python爬虫的简单入门(一)
    利用赫夫曼编码进行在线密码对话
    Markdown使用笔记
    SQL Server查询中特殊字符的处理方法 (SQL Server特殊符号的转义处理)
    decimal与float和double的区别
    dev、test、pre和prod是什么意思?
    bat代码中判断 bat是否是以管理员权限运行,以及自动以管理员权限运行CMD BAT
  • 原文地址:https://www.cnblogs.com/traveller-ly/p/9338628.html
Copyright © 2011-2022 走看看