Description
已知长度为n的非下降序列。
现在有q个查询,每个查询给出一个指定值。
输出序列中第一个大于等于给定值的元素下标,若不存在这样的元素,输出n+1。
输入格式
第一行一个整数n,为非降序列长度。1=<n<=100000。
第二行n个整数,为非降序列元素。所有元素的大小均在int范围内。
第三行包含一个整数q,为要询问的给定值个数。1=<q<=100000。
接下来q行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在int范围内。
输出格式
q行,每行一个整数,第一个大于等于给定值的元素下标,若不存在这样的元素,输出n+1。
输入样例
4
1 3 5 7
2
4
10
输出样例
3
5
提示
样例说明,大于等于4第3个元素,大于等于10不存在,所以输出5
题意:给一个非递减数组和若干询问,问数组中第一个大于等于询问数的位置 |
思路(DP + 预处理):
很直观的做法是直接对每次询问调用lowerbound函数,看起来不会超时(mlogn),但是确实TL了。 那么就要采用更优化的方法。
既然询问数量多,而数组又是提前给定的,那么我们对于这个数组,数轴上任意一个点对应在数组里面第一个大于等于的位置是可以直接知道的。 比如数组1 10 20 30如图
这里(2,10】区间内的元素全部都是指向10的(数组中第一个大于等于它的元素),(11,20】指向20,同理(21,30】指向30。
所以我们可以先map记录数组元素在坐标轴上的位置,然后从后往前遍历,状态转移方程就是
dp[i] = dp[i+1] (if i位置没有被数组中的元素占据)
如
dp[29] = dp[30] = 4(第四个位置)
dp[28] = dp[29] = 4
…
dp[21] = dp[22] = 4
dp[19] = dp[20] = 3
dp[18] = dp[19] = 3
…
dp[11] = dp[12] = 3
dp[9] = dp[10] = 2
…
以此类推
然后处理完数轴之后,对于每次询问数m,我们只需要调用dp[m]即可,达到询问O(1)的效果