zoukankan      html  css  js  c++  java
  • 2017 10 01国庆节大礼包 四校联考

    1.积木大赛

    (block.pas/c/cpp)

    【问题描述】

    为了庆祝国庆,厦门一中举办了一年一度的“积木大赛”。

    在2013年NOIP大赛中,夏夏同学己经搭建了宽度为n的大厦,其中第i块高度为hi。今年比赛的内容是对其NOIP2013搭建大厦进行扩建,使用的材料也都是体积为1正方体积木。

    今年搭建的规则是:如果要在某一个位置上放一个积木,必须满足它的左下、下方、右下都有积木(用二维坐标a表示,如果要在a[i,j]位置放积木,那么a[i-1,j-1]、a[i,j-1]、a[i+1,j-1]必须要有积木)。

      如果搭的积木大厦越高,夏夏同学就会觉得越有成就感,现有m个积木,问你能搭建的最大高度是多少?

    【输入】

    第一行两个用空格隔开的整数n和m,分别表示己搭好的宽度和可以使用的积木数量。

    后面有n行,每行一个整数hi表示己搭建的第i列积木的高度。

    【输出】

    一个整数,表示能搭建的最大高度。

    【输入输出样例】

    样例1

    样例2

    block.in

    block.out

    block.in

    block.out

    8 4

    3

    4

    2

    1

    3

    3

    2

    4

    5

    3 100

    3

    3

    3

    4

    【数据说明】

        30%的数据满足:n<=10;m<=1000。

        50%的数据满足:n<=100;m<=1000,000。

    70%的数据满足:n<=1000;m<=10,000,000。

        80%的数据满足:n<=10,000;m<=100,000,000。

    100%的数据满足:n<=100,000;m<=1000,000,000。

     

     

    题解:

    算法一:对于50%的数据:

    ①从高到低枚举每一个高度看是否能达到, 时间复杂度O(n);

    ②对于每一个高度,枚举最高点在哪一列,时间复杂度O(n);

    ③从当前枚举的最高列往两边递减判断是否合法,时间复杂度O(n);

    总时间复杂度O(n3)。

     

    算法二:对于70%的数据:

    在算法一中的第二步求高度时,使用二分答案,时间复杂度降为O(logn)。总时间复杂度为O(n2logn)。

     

    算法三:100%的数据:

      对于第二步和第三步,根据单调性,我们用L[i]表示在高度为H时第I列达到高度H时最左端的位置,R[i]为最右端的位置。通过O(n)的时间得到L,R,总的时间复杂度为O(nlogn)。

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cmath>
     4 #include <stdio.h>
     5 #include <string>
     6 #include <string.h>
     7 #include <numeric>
     8 using namespace std;
     9 int a[500001];
    10 long long s[500001];
    11 int l[500001];
    12 int r[500001];int n,m;
    13 int read()
    14 {
    15     char ch=getchar();
    16     int t=0;
    17     int f=1;
    18     while(ch>'9' || ch<'0')
    19       {ch=getchar();}
    20     while(ch>='0' && ch<='9')
    21       t=(t<<3)+(t<<1)+ch-'0',ch=getchar();
    22     return t;
    23 }
    24 bool check(int h)
    25 {
    26     memset(l,0,sizeof l);memset(r,63,sizeof r);
    27     int i;
    28     int inf=r[0];
    29     for (i=1;i<=n;i++)
    30         if (i+h-a[i]<=n)
    31             l[i+h-a[i]]=i;
    32     for (i=n;i>=1;i--)
    33         if (i+a[i]-h>0)
    34           r[i+a[i]-h]=i;
    35     
    36     for (i=1;i<=n;i++)
    37       l[i]=max(l[i],l[i-1]);
    38     for (i=n;i>=1;i--)
    39       r[i]=min(r[i],r[i+1]);
    40     for (i=1;i<=n;i++)
    41       {
    42           if (!l[i] || inf==r[i]) continue;
    43           if((1ll*(a[l[i]]+h)*(i-l[i]+1)>>1)+(1ll*(a[r[i]]+h-1)*(r[i]-i)>>1)-(s[r[i]]-s[l[i]-1]) <= m)
    44             return 1;
    45       }
    46     return 0;
    47 }
    48 int main()
    49 {
    50     
    51     n=read();
    52     m=read();
    53     int i;int l=0;
    54     for (i=1;i<=n;i++)
    55       a[i]=read(),s[i]=s[i-1]+a[i],l=max(l,a[i]);
    56     int r=2000000000;
    57     int mid;
    58     while(l<r)
    59       {
    60           mid=l+((r-l)>>1);
    61           if (check(mid))
    62             l=mid+1;
    63           else r=mid;
    64       }
    65     printf("%d
    ",l-1);
    66     return 0;
    67 }
    block
  • 相关阅读:
    day06作业
    day04_ATM项目说明书
    ATM+购物车基本思路流程
    装饰器、迭代器、生成器、递归、匿名函数、面向过程编程、三元表达式6
    day05函数部分
    自制七段数码管源码
    字符串格式化
    字符串表示
    格式化输出
    python入门——列表类型、元组、字典类型
  • 原文地址:https://www.cnblogs.com/yz12138/p/7619708.html
Copyright © 2011-2022 走看看