2015acm区域赛长春
2015-11-03 15:30
309 查看
F.Almost Sorted Array(hdu 5532)
LIS
题意:
给你一个数组,问你是否能去掉其中一个元素,使得剩下的是一个非递增序列,或非递减序列
数据范围:
n<=10^5,ai<=10^5
思路:
非递增和非递减分开处理(下面用单增来代替非递减)
判断能否单增,暴力地从左往右扫,扫到不满足单增的相邻两项,判断下是删除左边还是删除右边。然后继续扫,能扫到结尾就是ok,又遇到不满足的就不行了。这样做复杂度是O(n)
由于没有卡nlogn,所以你大可以套LIS模板,这里就是最长单增子序列,二分查找的时候要找上界不是下界。dp完看dp[n-1]是否合法,合法说明能到达这个长度,就是可以的
总结:求最长上升子序列,看长度能否达到n-1
G.Dancing Stars on Me(hdu 5533)
计算几何
题意:
给你n个点,问它们是不是组成一个正n边形
数据范围:
样例数<=300,n<=300,坐标绝对值<=10000
思路:
本题的坑是,坐标是整数输入,然后你会发现,除了正四边形,其他的正n边形都不可能同时为整数点。所以只要判断是不是正方形就可以了
正方形怎么判断?对坐标xy排序,然后第0个点和第3个点一定是对角线,然后就判断长度夹角什么的...
假如坐标不是整数点,我们要先求凸包,看凸包的点数是不是就是n,是的话再判断长度和夹角什么的,注意夹角要带方向
总结:判断n是不是4,是4的话判断是不是正方形
H.Partial Tree(hdu 5534)
背包问题
题意:
n个点,你要连n-1条边使之成为一棵树,并且使得这棵树的美丽值最大。
一棵树的美丽值等于每个点的美丽值之和,一个点的美丽值等于f(这个点的度数),f(x)是一个映射,题目会给出
数据范围:
n<=2015,f(i)<=10000
思路:
一棵树的总度数是2n-2,每个点的度数>=1,设点i的度数是ai,可以证明只要sum(ai)=2n-2并且ai>=1,那么这棵树必定能构造出来。也就是说,只要加上这些限制,度数可以随便调了。那这个题就和图论无关了,变成背包问题了
问题变成,有n个物品,每个物品在不同的花费有不同的价值,你要使得总花费等于2n-2的情况下,价值之和最大
令dp[i][j]表示第i个物品花费了j之后的最大价值
dp[0][0]=0,dp[0][j]=-inf
dp[i][j]=dp[i-1][j-k]+f(k),k>0
尽管空间可以压成一维,但是时间是O(n3)的,这样的dp显然不符合要求
这样考虑,每种度数的点有对应的度数花费,然后每种点有数量限制,这里的数量的含义是这种度数的点最多有多少个。虽然这样好像可以变成多重背包,但实际上也是无法确保dp[2n-2]就是用了n个点的
换另外一个思路,我们先让所有的点的度数为1,然后剩余的度数就是n-2,这时候每种物品的定义是某个点从度数为1升级为点数为i(i>1),对应的花费就是i-1,价值是f[i]-f[1]。
这样做避开了dp中物品数要等于n的限制,因为升级的点和不升级的点的总数总是等于n的,不过同时它们要非负。怎么确定它们都非负,由于升级的点数肯定是非负的,所以你要确保无升级的点数非负,也就是说升级的点数不能超过n。
我们看,物品的最小花费是1,而剩余的度数只有n-2,也就是你最多只能做n-2次升级,因此升级的点数不可能超过n,所以说这样处理可以无视掉点数等于n这个限制
某种物品的所有数量的总花费多于花费的上限,多重背包就能等价于完全背包。所以我们抽象出这些物品,然后直接跑完全背包,得到dp[n-2]。dp[n-2]是升级的价值,加上一开始让所有点的度数为1的价值n*f[1],就是答案
总结:把问题变成背包问题,先让所有点度数为1,再构造物品,跑完全背包
J.Chip Factory(hdu 5536)
字典树
题意:
给你一个数组,求max((ai+aj)⊕ak),要求i≠j≠k
数据范围:
n<=1000,ai<=10^9
思路:
暴力是O(n3)的不用多说,但据说现场能水过...后来hdu加强了数据,我加了个剪枝水过了,剪枝利用的原理是两个数的异或的二进制码的长度(没有前导零),一定是小于等于这两个数的二进制码的长度的最大值的,并且如果这两个数的长度不等,异或出来的数的长度就会等于这两个数长度较大的那个
剪枝就是,先把ai+aj枚举出来,然后分组,按它的二进制码长度分组。就刚才我们知道,只要存在ak的长度不是分组的最大长度,那么答案的长度一定是分组的最大长度。
我们枚举ak,先让ak和分组中最长的那组异或(当然要保证合法的前提),更新答案。然后看当前的最优答案的二进制码长度是否比ak要长。比ak长的话,就刚才的推理,说明了最终答案一定是分组的最大长度,那么既然ak已经和最大长度的ai+aj异或过了,那更短的那些就没必要异或了,就是这里剪枝了!如果答案和ak一样长,那我们老老实实地把剩余分组都异或一下。这样的复杂度应该也是O(n3)的,但是那个剪枝比较强,卡过去了
摆正姿势,正确做法是字典树,把所有的ak以二进制码的形式放进字典树(要包含前导零),然后枚举ai+aj。每次操作前先在字典树删除ai和aj,操作后再加回来,确保i≠j≠k。
操作是ai+aj也变成二进制码,然后在字典树上从高位开始走,在当前的位,尽量选与ai+aj这个位上不同的枝条。比如ai+aj的这个位是1,那去0,没有这个枝条才去1。这样子从高位到低位考虑,每步的决策必然是最优的,在走的时候记得一边走一边算答案就是了
数的二进制码的长度默认是31,总的复杂度是O(31*n2+31n)=O(n2)
总结:用字典树保存ak,枚举ai+aj在字典树上贪心决策
L.House Building(hdu 5538)
水题
题意:
给你一个矩阵,它是一间屋子的平面图。矩阵每个格的数字表示屋子在这个点的高度,你需要给这间屋子的表面涂色(不包括地下部分),问要涂多少格
数据范围:
行列<=50,高度<=1000
思路:
对于某个点的一条柱,它有五个面要考虑(底面不用),向天的面直接+1就好,其他四个面就要看相邻的点的柱子高度。某个面对应的相邻柱子高度比自己高的话,那这个面就没必要涂了。否则,要涂的格就是高度差。
因此对于一个点,你遍历它的邻居就知道这个点的柱子要涂多少格。总的复杂度是O(4*row*col)=O(n2)
在数组的周围一圈标上零,可以省去边界的判断
总结:遍历每个点,考虑它的邻居的高度,计算这个点要涂色的格子数
LIS
题意:
给你一个数组,问你是否能去掉其中一个元素,使得剩下的是一个非递增序列,或非递减序列
数据范围:
n<=10^5,ai<=10^5
思路:
非递增和非递减分开处理(下面用单增来代替非递减)
判断能否单增,暴力地从左往右扫,扫到不满足单增的相邻两项,判断下是删除左边还是删除右边。然后继续扫,能扫到结尾就是ok,又遇到不满足的就不行了。这样做复杂度是O(n)
由于没有卡nlogn,所以你大可以套LIS模板,这里就是最长单增子序列,二分查找的时候要找上界不是下界。dp完看dp[n-1]是否合法,合法说明能到达这个长度,就是可以的
总结:求最长上升子序列,看长度能否达到n-1
G.Dancing Stars on Me(hdu 5533)
计算几何
题意:
给你n个点,问它们是不是组成一个正n边形
数据范围:
样例数<=300,n<=300,坐标绝对值<=10000
思路:
本题的坑是,坐标是整数输入,然后你会发现,除了正四边形,其他的正n边形都不可能同时为整数点。所以只要判断是不是正方形就可以了
正方形怎么判断?对坐标xy排序,然后第0个点和第3个点一定是对角线,然后就判断长度夹角什么的...
假如坐标不是整数点,我们要先求凸包,看凸包的点数是不是就是n,是的话再判断长度和夹角什么的,注意夹角要带方向
总结:判断n是不是4,是4的话判断是不是正方形
H.Partial Tree(hdu 5534)
背包问题
题意:
n个点,你要连n-1条边使之成为一棵树,并且使得这棵树的美丽值最大。
一棵树的美丽值等于每个点的美丽值之和,一个点的美丽值等于f(这个点的度数),f(x)是一个映射,题目会给出
数据范围:
n<=2015,f(i)<=10000
思路:
一棵树的总度数是2n-2,每个点的度数>=1,设点i的度数是ai,可以证明只要sum(ai)=2n-2并且ai>=1,那么这棵树必定能构造出来。也就是说,只要加上这些限制,度数可以随便调了。那这个题就和图论无关了,变成背包问题了
问题变成,有n个物品,每个物品在不同的花费有不同的价值,你要使得总花费等于2n-2的情况下,价值之和最大
令dp[i][j]表示第i个物品花费了j之后的最大价值
dp[0][0]=0,dp[0][j]=-inf
dp[i][j]=dp[i-1][j-k]+f(k),k>0
尽管空间可以压成一维,但是时间是O(n3)的,这样的dp显然不符合要求
这样考虑,每种度数的点有对应的度数花费,然后每种点有数量限制,这里的数量的含义是这种度数的点最多有多少个。虽然这样好像可以变成多重背包,但实际上也是无法确保dp[2n-2]就是用了n个点的
换另外一个思路,我们先让所有的点的度数为1,然后剩余的度数就是n-2,这时候每种物品的定义是某个点从度数为1升级为点数为i(i>1),对应的花费就是i-1,价值是f[i]-f[1]。
这样做避开了dp中物品数要等于n的限制,因为升级的点和不升级的点的总数总是等于n的,不过同时它们要非负。怎么确定它们都非负,由于升级的点数肯定是非负的,所以你要确保无升级的点数非负,也就是说升级的点数不能超过n。
我们看,物品的最小花费是1,而剩余的度数只有n-2,也就是你最多只能做n-2次升级,因此升级的点数不可能超过n,所以说这样处理可以无视掉点数等于n这个限制
某种物品的所有数量的总花费多于花费的上限,多重背包就能等价于完全背包。所以我们抽象出这些物品,然后直接跑完全背包,得到dp[n-2]。dp[n-2]是升级的价值,加上一开始让所有点的度数为1的价值n*f[1],就是答案
总结:把问题变成背包问题,先让所有点度数为1,再构造物品,跑完全背包
J.Chip Factory(hdu 5536)
字典树
题意:
给你一个数组,求max((ai+aj)⊕ak),要求i≠j≠k
数据范围:
n<=1000,ai<=10^9
思路:
暴力是O(n3)的不用多说,但据说现场能水过...后来hdu加强了数据,我加了个剪枝水过了,剪枝利用的原理是两个数的异或的二进制码的长度(没有前导零),一定是小于等于这两个数的二进制码的长度的最大值的,并且如果这两个数的长度不等,异或出来的数的长度就会等于这两个数长度较大的那个
剪枝就是,先把ai+aj枚举出来,然后分组,按它的二进制码长度分组。就刚才我们知道,只要存在ak的长度不是分组的最大长度,那么答案的长度一定是分组的最大长度。
我们枚举ak,先让ak和分组中最长的那组异或(当然要保证合法的前提),更新答案。然后看当前的最优答案的二进制码长度是否比ak要长。比ak长的话,就刚才的推理,说明了最终答案一定是分组的最大长度,那么既然ak已经和最大长度的ai+aj异或过了,那更短的那些就没必要异或了,就是这里剪枝了!如果答案和ak一样长,那我们老老实实地把剩余分组都异或一下。这样的复杂度应该也是O(n3)的,但是那个剪枝比较强,卡过去了
摆正姿势,正确做法是字典树,把所有的ak以二进制码的形式放进字典树(要包含前导零),然后枚举ai+aj。每次操作前先在字典树删除ai和aj,操作后再加回来,确保i≠j≠k。
操作是ai+aj也变成二进制码,然后在字典树上从高位开始走,在当前的位,尽量选与ai+aj这个位上不同的枝条。比如ai+aj的这个位是1,那去0,没有这个枝条才去1。这样子从高位到低位考虑,每步的决策必然是最优的,在走的时候记得一边走一边算答案就是了
数的二进制码的长度默认是31,总的复杂度是O(31*n2+31n)=O(n2)
总结:用字典树保存ak,枚举ai+aj在字典树上贪心决策
L.House Building(hdu 5538)
水题
题意:
给你一个矩阵,它是一间屋子的平面图。矩阵每个格的数字表示屋子在这个点的高度,你需要给这间屋子的表面涂色(不包括地下部分),问要涂多少格
数据范围:
行列<=50,高度<=1000
思路:
对于某个点的一条柱,它有五个面要考虑(底面不用),向天的面直接+1就好,其他四个面就要看相邻的点的柱子高度。某个面对应的相邻柱子高度比自己高的话,那这个面就没必要涂了。否则,要涂的格就是高度差。
因此对于一个点,你遍历它的邻居就知道这个点的柱子要涂多少格。总的复杂度是O(4*row*col)=O(n2)
在数组的周围一圈标上零,可以省去边界的判断
总结:遍历每个点,考虑它的邻居的高度,计算这个点要涂色的格子数
相关文章推荐
- UVALive 7146 Defeat the Enemy (贪心)
- 2015acm区域赛沈阳
- 2015 长春、沈阳区域赛总结
- 拆点+BFS______Meeting( hdu 5521 2015区域赛沈阳站 )
- HDU 5558
- UVALive-7303- Aquarium【最小生成树】【连通块】
- UVALive-7304 - Queue of Soldiers 【动态规划】【组合函数】【好题】
- Regionals 2015 >> Asia - Tehran >> 7527 - Funfair【贪心】【dp】
- 2015acm区域赛北京
- 2015 ICPC && CCPC - 小记
- HDU 4462 Scaring the Birds(dfs)
- hihoCoder 1257 Snake Carpet (构造题+详解) 2015北京区域赛
- HDU - 5976 简单逆元
- HDU 5532 2015ACM-ICPC长春赛区现场赛F题
- HDU 5533 2015ACM-ICPC长春赛区现场赛G题
- HDU 5534 HDU 5532 2015ACM-ICPC长春赛区现场赛H题
- HDU 5536 2015ACM-ICPC长春赛区现场赛J题
- HDU 5510 2015ACM-ICPC沈阳赛区现场赛B题
- HDU 5512 2015ACM-ICPC沈阳赛区现场赛D题
- HDU 5521 2015ACM-ICPC沈阳赛区现场赛M题