百度之星1A初赛

1001 度度熊拼三角

难度 0/5

我们可以贪心地考虑这个问题。
先找到长度最长的三根木棒。
如果它们能构成三角形,那么答案就是它们的长度和。
否则我们会发现,最长的木棒过于长了,没有任何木棒能和它拼。
那么我们直接将其删除,不会影响答案。然后重复此流程即可。

最终做法即是:对木棒进行从大到小排序,每次检验连续的三根,若能构成三角形即为答案。时间复杂度\(O(N \log N)\)

1002 度度熊学队列

难度 1/5

由于有频繁的连接操作和前后插入,显然要用双向链表来模拟此题。
选手可能会被“翻转”限制住思路,而尝试去写启发式合并的log做法,或者是带翻转标记的链表做法。
其实对于每一个“双端队列”,我们可以直接无脑开一个双向链表(无须记录谁前谁后),同时记录一下首和尾指针的位置。每次合并的时候直接 \(O(1)\) 暴力“对接”即可。
时间复杂度为\(O(Q)\)

1003 度度熊剪纸条

难度 2/5

这是一道比较简单的签到题,有不同的做法。
这里给出一个较为严谨的做法。

首先,对于一段连续的\(1\),在中间剪是没有意义的。
进一步思考,每次必然会剪在一段\(1\)的两侧。

值得注意的是,有一些情况需要特殊判断。

具体地,对于中间一段连续的 \(1\) ,我们剪两次才能把它剪下来(头和尾),不妨把代价记为\([1,1]\)
如果一段 \(1\) 在开头,它的头是不用剪下来的,不妨把代价记为 \([0,1]\)
同理,如果一段 \(1\) 在结尾,它的尾是不用剪下来的,可以把代价记为\([1,0]\)

最后还有一个问题:
在我们拼出的最终态中,最后一个\(01\)串不要求全\(1\)
换句话说,我们可以把最多一个代价为\([x,y]\)的段改成代价为\([x,0]\)

现在,我们要在这些集合里挑选一些段,使得中括号里代价和不超过\(K\)
分情况讨论一下,排序后从大到小选即可。
复杂度为\(O(N \log N)\)

1004 度度熊看球赛

难度 3/5

此题有两种做法,这里介绍一种比较精妙的DP做法。
先把一组情侣的两个人看做是相同的(最后方案数要乘上\(2^N\))。

\(f_{i,j}\) 表示,一共有 \(i\) 对情侣,且正好有 \(j\) 对是挨着坐的。
每次考虑把第 \(i+1\) 对情侣放进去:
(1)这对情侣合在一起放。
①放在某一对挨着的情侣中间(拆散他们):\(F_{i+1,j}+=F_{i,j} \times j\)
②放在情侣之间的空隙里:\(F_{i+1,j+1}+=F_{i,j} \times (2 \times i-j+1)\)
(2)这对情侣分开放。
①他们各自都拆散了一对情侣:\(F_{i+1,j-2}+=F_{i,j} \times (j \times \frac{(j-1)}{2})\)
②只有一个人拆散了一对情侣:\(F_{i+1,j-1}+=F_{i,j} \times (2 \times i-j+1) \times j\)
③没有情侣被拆散:\(F_{i+1,j}+=F_{i,j} \times ((2 \times i-j+1) \times \frac{2 \times i-j}{2})\)

这样我们就能在 \(O(N^2)\) 的时间里预处理出所有情况。
对于每一组询问,我们只要 \(O(N)\) 扫一遍计算一下答案即可。

1005 度度熊玩数组

难度 4/5

每次使一个点失效,可以倒过来做,变成每次使一个点生效,然后询问所有有效区间权值和最接近K的值。

区间 \([l,r]\) 的权值和 \(=S_r-S_{l-1}\)\(S\) 为前缀和数组。
区间 \([l,r]\) 的权值和也 \(=H_l-H_{r+1}\)\(H\) 为后缀和数组。
可以预处理前缀和 \(S\) 和后缀和 \(H\),开两个 \(set\) ,分别存放该区间内的 \(S\)\(H\) 数组。
每次使一个点生效时,相当于合并两个区间。计算答案的时候可以像启发式合并一样枚举小区间的每个点作为区间的其中一个端点,然后在 \(set\) 里询问并把 \(set\) 启发式合并。

也可以开两棵主席树,在树上询问最接近的值。

复杂度\(O(N \log^2 N)\)

1006 度度熊算算术

难度 5/5

先考虑是一条链的情况。
因为有乘积不好处理,而数据可以认为是随机的,那么我们可以把每次的乘积取log后进行操作。
取log比较慢可能会影响复杂度,所以我们要预处理 \(1\) ~ \(10000000\) 的对数。注意可以利用对数的性质,只在质数出求。

这样我们可以快速写出一个\(N^2 \times K\)的DP。
\(f[i][j]\)表示考虑前i个数,选了j段的最大乘积的对数。
每次我们枚举\(k<i\),用\(f[k][j-1]+log(sum[k+1..i]))\)来更新\(f[i][j]\)
注意到这个DP是有决策单调性的,理论上我们可以做到\(N \times K\),但是采用比较方便的 \(NK \log N\) 也行。

现在只需知道环怎么做就行了。
先考虑一些特殊情况,比如\(K \leq 10\)\(K=N\) 的情况。
\(K \leq 10\)时,因为只划成常数块,我们枚举每一个开头做一遍链即可。
\(K=N\) 时,因为划成了 \(N\) 块,其实我们随便选一个点当开头都等价,做一遍链的情况即可。

那么我们不禁想到:\(K\) 小的时候暴力做,K大的时候直接随机一些位置当起点做即可(因为合法的起点个数有 \(K\) 个)
假设每次随机 \(\lfloor \frac{N}{K} \rfloor \times G\)个点( \(G\) 是一个小常数)。
对于所有情况打个表,发现 \(N \leq 1000\) 时,如果取 \(G=10\),那么能随机到某一个合法起点的概率是99.9%。
如果非酋不放心,可以取 \(G=15\),此时正确率就是99.997%了,必然能通过此题。

最后的复杂度就是 \(O(N^2 \times G)\) 或是 \(O(N^2 \times G \times \log N)\),常数较小。

posted @ 2018-08-11 17:00  了491  阅读(634)  评论(0编辑  收藏  举报