2019.8.9 Contest

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]必须要有积木)。

img

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

【输入】

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

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

【输出】

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

【输入输出样例】

样例输入1 样例输出1 样例输入2 样例输出2
8 4 5 3 100 4
3 3
4 3
2 3
1
3
3
2
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;1<=hi<=100000。

二分答案+双指针扫描

二分搭建的高度,最低为maxh+1,最高为maxh+sqrt(m)+1

如何在O(n)时间内check呢?

对于搭建积木,我们要搭出一个金字塔形,但是,并不是要搭建整个金字塔形,有时候只要搭建部分即可,如图:

img

我们仅需搭建绿色部分,而不需要搭建蓝色方框内的整个金字塔

如何找到绿色部分呢?

l为绿色部分的左边界,r为绿色部分的右边界,x为当前要搭建的金字塔顶,h为大金字塔塔高

我们需要在搭建的金字塔所需积木=整个大金字塔所需积木-黄色部分所需积木-紫色部分所需积木-棕色部分所需积木

设黄色部分高为a,则a=h-(x-l)(即图中6-1=5),黄色部分所需积木为a*(a+1)/2

同理,能算出紫色部分所需积木。

棕色部分所需积木=r前面所有已有积木-l前面所有已有积木。我们想到了什么?前缀和

这样,绿色部分所需积木就算出来了,我们比较它与m的大小关系即可

等等!还没说l和r怎么求呢?

我们发现,对于一个位置x,如果能找到它所对的l,那么对于位置x-1,它的l必≤位置x所对的l,且从位置x所对的l ~x-1绝对不满足能做绿色部分的左边框。因为在向左移的过程中,左边的每个位置的h的要求总是增大的(金字塔形)

所以l具有单调性。我们从n到1扫描每个位置,如果当前的l不满足h[l]<h-(i-l)(即不能做绿色部分的左边框),那么我们l—,直到满足要求,然后我们拿一个数组记下每个位置的l

img

对r也是一样,只要从左往右扫描即可

注意:前缀和要开long long,二分答案的下限一定要从maxh+1开始(不然会引发奇奇怪怪的事故),lr不能小于1或大于n(超出给定范围n外的位置不能放积木)


如果您是大佬,您也可以用主席树优化过此题。

img



2.爱心月饼

(cake.pas/c/cpp)

【问题描述】

中秋节马上就要到了,电脑组的女生们准备自己动手做月饼给大家分享,烘培老师告诉她们做月饼需要面粉和馅,女孩子们网上各种搜索,采购到了M种面粉和N种口味不同的馅,其中第i种面粉有mi斤,第i种馅有ni斤。这里的种类从0开始标号。

经过实践,女孩子们发现每份月饼需要1斤面粉和1斤馅,为了让收到礼物的同学感到很特别,她们决定不让两份月饼用同一种面粉和同一种馅做成(即每种月饼之间面粉和馅的种类至少有一个不同),女孩子们现在就想知道她们采购到的这些材料可以做多少份爱心月饼?这种简单的问题就交给你啦,她们还得赶着去做月饼呢。

【输入】

由于输入很大,所以使用一种方法生成输入。

l m0= m0

l mi+1 = (mi* 58+md) mod (N + 1)

l n0 = n0

l ni+1 = (ni *58 + nd) mod (M + 1)

第一行6个整数为M,N,m0,md,n0,nd

【输出】

​ 输出一行,为最多能做月饼的份数。

【输入输出样例】

对于10%的操作,$N,M ≤ 5$.

对于30%的操作,$N,M ≤ 1000$.

对于50%的操作,$N,M ≤ 10^5 $.

对于100%的操作,$1 ≤ N,M ≤ 2.5 ∗ 10^6$ , $0 ≤ m0,md ≤ N$, $0 ≤ n0, nd ≤ M$.

【数据说明】

cake.in cake.out
2 3 1 3 1 0 2
5 8 1 2 3 4 19

img


3.直径

(tree.pas/c/cpp)

【题目大意】

收到礼物的同学们用爱心月饼摆出了一棵有$n$个点的树,边有长度。然后得意地给其他同学出了一个问题:对于每一条边,把这条边删掉之后得到的两棵树的直径是多少?

【输入文件】

第一行一个正整数$n$,表示树的点数

接下来的$n-1$行每行有三个数$u$, $v$, $w$, 表示有一根树枝连接$u$和$v$,长度为$w$

【输出文件】

对于第$i$条边(从$1$开始标号),你将会得到$2$个答案$P_i$和$Q_i$,我们令$ans_i=max(P_i,Q_i)23333+min(P_i,Q_i)2333+233ii+23i+2$,请输出一个数$S$表示所有$ans_i$的和对*2333333333333333取模的值

【样例】

输入 输出
10 735923484
1 2 234
2 9 936
9 5 784
5 3 105
2 8 775
8 10 368
10 6 1003
9 4 670
4 7 417

【数据规模与约定】

对于10%的数据,保证n≤300

对于30%的数据,保证n≤5000

对于50%的数据,保证n≤100000

对于70%的数据,保证n≤1000000

对于100%的数据,保证n≤4000000,w≤1000000


10分算法:

对于每条删边在两端$O(n^2)$求树的直径

时间复杂度$O(n^3)$,空间复杂度$O(n)$

30分算法:

对于每条删边在两端$O(n)$求树的直径

时间复杂度$O(n^2)$,空间复杂度$O(n)$

50分算法:

可以写个点分治冷静一下

要是你真的去写了你就确实应该冷静一下了

时间复杂度O(nlogn),空间复杂度O(n)

100分算法1(不推荐):

树形DP

需要先计算一个点向下走的最大值,次大值,第三大值。

然后计算一个点向上走的最大值。

然后计算这个点和它的父亲的边断掉后这个子树的答案,这个比较好计算。

最后计算这个点和它的父亲的边断掉后这个子树之外的答案,分三种情况:

1、它的父亲的其他儿子的向下答案

2、它的父亲断边之后的答案

3、它的父亲向上的答案

注意你不能对每个点扫一遍它的父亲的其它儿子,一个菊花树就能卡掉,要维护一个前缀的最值和一个后缀的最值。

该方法常数可能略大

时间复杂度O(n),空间复杂度O(n)

100分算法2:

先求出树的直径,然后分删掉的边是否在直径上讨论。

删掉的边不在直径上时,其中一端的答案就是直径,另一端做十分简单的树形DP即可。

考虑自左到右计算删掉的边在直径上的左边的答案(右边同理),使用类似NOIP2016 D2T2的方法即可。

时间复杂度O(n),空间复杂度O(n)


img


得分 : 160

-------------本文结束(づ ̄ 3 ̄)づ~感谢您的阅读(*╹▽╹*)-------------