标签:tab 比赛 ret name alt size 判断 padding 描述
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 }
标签:tab 比赛 ret name alt size 判断 padding 描述
原文地址:http://www.cnblogs.com/yz12138/p/7619708.html