SCPC Round #13(Div.2)
第二十届西南科技大学ACM大学生程序设计竞赛题解
(xxx):代表idea贡献者
前言:感谢选手们的参与,对于比赛中的锅,深感歉意。以下是题解部分。
我算算算(charan)
知识点:数学
题意:给定一个数组 ,问多少种不同排列
经过生成方式
可以得到
题解:
由 的性质,我们可以对数组
中任意相邻元素进行分类讨论。
为方便,我们用 表示:
,
- 若
,则在原排列
即
固定,不对方案数造成影响
- 若
,则在原排列
,
可以选择
之间的数,但是在
之后已经选择
个元素且其中一个元素为
,所以
仅可选择剩余的
。由乘法原理可以将答案与
相乘。
- 若
,显然不存在这中情况,方案数则为 0.
还需要注意,特判 。
图腾(charan)
知识点:线段树,STL,思维
题意:初始给定 个图腾,后有
次询问,每次询问分两种,一种单点插入一个图腾,另一个是区间查询能量,每个整数点计算公式为:
。
题解:
对于第一个操作:在某个点加入图腾,对于该操作,会发现其实插入一个图腾,影响的仅是原本该位置左边最近和右边最近
的两个图腾之间的点。对于寻找最近的点,可以用
中
来寻找右边最近,用
来寻找左边。然后将当前插入点
的能源先清零,然后用线段树将
区间内能源全改为
,同理将
区间内全改为
,即可。但是该修改不能将每个点都修改(若全修改复杂度为
),此时可以借助带
的线段树来实现。使得该操作复杂度为
对于第二个操作:只需要在线段树中添加一个维护区间和的即可,该复杂度为。
祖玛(wzy)
知识点:思维,manacher 或 二分+hash
题意:给定一个字符串 ,问放入一个字符后,通过碰撞消去的小球的最大分数。
题解:
首先会发现对于一个连续的由相同字母组成的子串,该子串在碰撞的时候可以等价于一个该字母,分数为该字母分数×子串长度。
将字符串 每个连续的由相同字母组成的子串缩成一个字母后得到新的字符串
。当进行操作时候,肯定选择为某个回文串,因为对于回文串,当我们发射一个小球于回文串中点,可以使得该回文串全部消失。
所以我们可以用 manacher 算法,去预处理出 所有点的回文半径,放入
,或用二分+ hash 来代替manacher,对于每一个点去二分回文半径。然后用前缀和去预处理出
的分数,放入
。然后暴力枚举
所有的点,对于点
其最大可以获得分数为
再加上插入的点
,和答案取
即可。
朔月望(asoulcoming)
知识点:模拟
题意:给定五个牌,第1、2、4 为齐夏的牌,第1,3,5为嘉心糖的牌。然后遵循游戏规则进行一把游戏。问齐夏是否会获胜?
题解:
按照题意先将牌变换成点数后进行胜利第一条件的判断:对点数进行相加看是否大于 ,然后比较大小,若胜利再判断第二胜利条件,按照牌型优先级依次比较即可,若平局则删去点数后重新比较,直到平均(即齐夏没赢),或分出胜负。
我数数数数数数(charan)
知识点:树形dp
题意:给定一棵顶点数为 的树,问导出子图中任意两个节点间简单路径长度
的方案数为多少。
题解:
由于要求导出子图两节点间简单路径长度。所以对于一个节点,与他相连也至多一个节点。所以对于任意一个节点,有且仅有三种状态:
- 不选择当前节点。
- 选择当前节点,但是不与子节点相连。
- 选择当前节点,与子节点相连
从而可以设 表示第
个节点第
个状态的方案数。
初始化时候,叶子节点的
对于当前节点 ,如何从子树转移?
-
不选择当前节点。则可以从子节点的任意状态转移。
-
选择当前节点,但是不与子节点相连。则可以从子节点的 状态 1 (不选择子节点)转移。
-
选择当前节点,且与子节点相连。则任意选择一个子节点的状态 2 与该节点相连,别的子节点仅可选取状态 1、状态 2、状态 3。
该公式需要
复杂度,但是我们可以利用
来进行
的转移:
最后答案即为 。注意对答案及时的取模!
异或症(ARUME)
知识点:思维,位运算
题意:给定一个长度为 的排列,可以任意次操作,选择两个数
使
,操作后再施行
问最大的
题解:
不妨设 的二进制最高位为
。对于
的二进制位中,从第
位到第
位,若
第
位为
, 则可以对
,经过此次操作后即可使得
。然后对第
个数到第
个数异或自身即可。既可以得到操作后的序列
,操作后再执行
,即可得到最终序列
即可得到最大和为:
又双叒叕分糖果(Small Orange)
知识点:思维,STL
题意:两个糖果包有 和
种不同重量的糖果,但总数相同。现在要把两个糖果包糖果各丢弃一半,并且尽可能多的从两个糖果包中选择糖果做成一个新的糖果包,且新糖果包没有相同重量的糖果。问新糖果包最多可能有多少种糖果?
题解:
首先将第一个糖果包的重量放入 中存储,第二个糖果包的重量放入
存储,同时记录重复重量的糖果
。
然后可以知道第一个糖果包有第二个糖果包没有的为 ,第二个糖果包有第一个没有的
。两边尽可能的取
,若取不到的时候再拿相同的来补充。即最终答案为:
端午重现。祝全体老师、同学、志愿者们,端午安康!(风前絮)
知识点:计算几何
题意:给定四个平面坐标 ,问
的距离。
题解:可以写一个 函数来计算两点之间的距离,然后调用即可。
double dis(Point a,Point b)
{
return sqrt( (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) );
}
能源(TANGhaozhan)
知识点:排序
题意:给定 个庇护所,每个至少需要
能源,
个电池,每个电池提供
电源。每个庇护有且仅能装一个大于等于其所需能源的电池。问最后提供能源总和最少多少?
题解:
从贪心的角度来看,提供给庇护所的电池能源要尽可能接近其所需的能源,否者显然不会更优。
所以对 数组排序。然后维护一个指针
,指向
数组。数组
从小到大遍历,对于每一个
若当前的
,则就让
提供给
庇护所,把能源加入答案,
;否者
,直到找到
。
简单的求和 (sisanjiujiu)
知识点:数学,wqs二分,斜率优化dp
题意:给定,和数组
。定义
,将序列
分成
段,求
的最小值。
题解:
可以将 简化:
可以预处理前缀和 ,从而得到
对于恰好分成 段问题,若用暴力的方法取处理通常都是
,但经常都是使用 wqs 二分来处理,可以降一维达到
。二分斜率找到与原凸包相切的地方,找到此时的
方程中的最佳段数
与原
进行比较,来更新二分区间。二分斜率通常都是多加一个常数
,表示多划分一段的增量,原公式可以继续化简为斜率优化dp常见方程式,即
:
此时
套用模板即可解出答案。但要注意特判平台位置!
拾取糖果(charan)
知识点:数论
题意:在 直角坐标平面上有
个糖果,每个糖果用坐标
表示。你可以在 任意一条 穿过原点的直线上拾取糖果,问 最多 能拾取多少个糖果?
题解:
由于经过原点,即 ,即通过记录每个
对应着几个点,去寻找最大值即可。但是由于该
为小数,有精度问题。所以需要使用
去化简分式保存于
中。然后最后用
遍历即可。
枝江一梦(asoulcoming)
知识点:预处理
题意:给定二维平面,初始在 正半轴有
点都在
处。有
次操作,每次操作会使得在
点提高
然后扩散其周围,但是
递减,直到
。问最后正半轴
的
轴坐标。
题解:
对于每次操作,只要维护一个前缀差分,和一个后缀差分
,还有对于每个
位置的增量
。前后缀维护每个位置应当减少
的量。例如若在
提高
点。则
,预处理后先从前往后遍历,处理右边的扩散,再从后往前遍历,处理左边的扩展。代码如下:
int add = 0;
int sum = 0;
for(int i=1;i<=n;i++)
{
sum += w[i] - add;
add += pre[i];
ans[i] = sum;
}
add = 0;
sum = 0;
for(int i=n;i>=1;i--)
{
sum += w[i] - add;
add += pos[i];
ans[i] += sum - w[i];//注意此时w[i]加了两次,所以应当减去一次。
}
最后输出ans数组即可。
简单动态规划(Small Orange)
知识点:思维,预处理,扫描线,前后缀和
题意:给定一个长度为 的序列
,可以做任意次操作进行修改序列,但操作花费不同,问操作后使序列满足公差为
的等差数列的最小花费。
题解:
首先可以对原序列排序,因为交换元素不需要花费。排序后的序列必然是最后的顺序,可以比较简单证明:
若排序后的序列顺序不是最后顺序,则存在两个下标
,在排序后
,但是
,很明显,两个之间必然有交集,即为重复部分,该部分肯定会使得答案不是最优。证毕。
既然为最后序列,我们可以对该序列减去公差,,即可消去等差数列的性质,得到的序列
,我们只需要他相同即可。
对于最终答案,其某个位置必然为 或
,可以简单证明:
若最终答案不为该三个位置。则有两种情况
- 可能在任意
两个数(或三个及以上数)之间。
- 若两个数之间,则和在该数一样的操作次数,即花费不变。
- 若三个及以上之间,两边不均分的情况下,显然在中间会使得一边数多的操作次数增大,即更不优。若均分,则和两数之间相同,即操作次数不变。
- 可能在左端点左边或右端点右边
- 若在两端,显然步数要多走
的倍数,显然不优 。
(因为三个位置中必然有奇数和偶数,即可以不用讨论奇偶的影响,讨论中的操作仅为
的操作)
所以我们可以把所有可能的位置放入 中排序后去重,然后判断取哪一个点的可以使得花费最小。
如何判断选取某一点的花费?
可以前后缀预处理处值的总和,奇数个数总和,偶数个数总和,然后对于某个可能的取值 找出其在
中的位置
,对其前面的不同奇偶性的数
,对后面不同奇偶性的
,然后差值总和除
,乘上操作花费即为该点的花费,取min 即可取得最小花费。