1. 程式人生 > >2017 10 01國慶節大禮包 四校聯考

2017 10 01國慶節大禮包 四校聯考

play sin getch colspan check ems algorithm 坐標 border

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\n",l-1);
66     return 0;
67 }
block

2017 10 01國慶節大禮包 四校聯考