2019年9月1日CF群打卡题: 1187C, 1187D.
1187C Vasya And Array
描述
有一个未知数组nums, 现在已知的信息是一些三元组a.
a[0] == 1表示nums数组的[a[1], a[2]]闭区间是非递减的.a[0] == 0表示nums数组的[a[1], a[2]]闭区间不是非递减的(有点绕, 其实就是这段区间内至少存在一个递减的地方nums[i-1]>nums[i]).
利用已知信息, 建造一个符合条件的nums. 如果这样的数组不存在, 打印NO.
思路
对于a[0] == 1的情况, nums数组的(a[1], a[2]]左开右闭区间内所有下标i, 必须都满足nums[i-1] <= nums[i](可以看做一种限制或者标记).
先用一个数组存这些标记. 然后对于每一个a[0] == 0的情况, 搜索[a[1], a[2]], 如果找不到任何一个未被标记的, 说明此区间内必须非递减, 不能满足要求, 可以直接返回NO.
为了表示简单, 可以把非递减当做不变, 在每一个必须递减的地方, 我们给上一个值减掉1来填充当前值.
代码
1 | def do(): |
1187D Subarray Sorting
描述
给一个数组a和目标数组b, 对于a来说, 允许任意次, 任意subarray的从小到大排序. (比如对a的subarray a[1:4]排序, 其他位置不变).
问是否可以从a转换成b(YES or NO).
思路
类比冒泡排序, 每次排序完成后, (这个区间内的)最小值都会跑到区间最前边. 不是最小的值会被比它小的挡住, 不会跑到最前边. 废话
比如, 对于b[0]来说, 需要找到b[0]在a中出现的第一个位置i, 然后排序a[0:i+1].
- 如果
b[0]是a[0:i+1]的最小值, 那么b[0]就由a产生了. - 否则, 有更小的值存在于
[0,i-1]区间内, 阻止了a[i]在排序过程中的前进. (想一想, 最早出现的a[i]都不行, 后面的更不行了, 同样会被[0,i-1]内的更小值挡住, 甚至i后面还有更多的更小值). 这样,b[0]永远也不能由排序得到. 结果一定是NO. b[0]由a成功产生的话, 对于b[1]做同样的操作. 需要注意的是, 每次用完a中的一个数, 都要把它置为无穷大, 不会影响以后的区间最小值查询.- 所以本题化简为了一个单点更新和区间查询的问题. (线段树RMQ). (类比skyline problem, 那个是区间更新, 单点查询)
代码
会TLE, 但是所有长度短于300000的case都能过…正确性没问题, CF的OJ对Python不友好.
1 | import collections |