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 |