Skip to content

706B. Interesting drink

binary search/dp/implementation, 1100, https://codeforces.com/problemset/problem/706/B

Vasiliy likes to rest after a hard work, so you may often meet him in some bar nearby. As all programmers do, he loves the famous drink "Beecola", which can be bought in n different shops in the city. It's known that the price of one bottle in the shop i is equal to x~i~ coins.

Vasiliy plans to buy his favorite drink for q consecutive days. He knows, that on the i-th day he will be able to spent m~i~ coins. Now, for each of the days he want to know in how many different shops he can buy a bottle of "Beecola".

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the number of shops in the city that sell Vasiliy's favourite drink.

The second line contains n integers x~i~ (1 ≤ x~i~ ≤ 100 000) — prices of the bottles of the drink in the i-th shop.

The third line contains a single integer q (1 ≤ q ≤ 100 000) — the number of days Vasiliy plans to buy the drink.

Then follow q lines each containing one integer m~i~ (1 ≤ m~i~ ≤ 10^9^) — the number of coins Vasiliy can spent on the i-th day.

Output

Print q integers. The i-th of them should be equal to the number of shops where Vasiliy will be able to buy a bottle of the drink on the i-th day.

Example

input

5
3 10 8 6 11
4
1
10
3
11

output

0
4
1
5

Note

On the first day, Vasiliy won't be able to buy a drink in any of the shops.

On the second day, Vasiliy can buy a drink in the shops 1, 2, 3 and 4.

On the third day, Vasiliy can buy a drink only in the shop number 1.

Finally, on the last day Vasiliy can buy a drink in any shop.

2021fall-cs101,刘佳霖,implementation

①用defaultdict 函数把字典默认值设为n,这样如果钱特别多就都给他买了,之后循环可以少点; ②需要考虑多家店同一价格的情况,这样加一块钱,能买的店会可能多好几家。

python
from collections import defaultdict
n = int(input())
*x, = map(int, input().split())
x.sort()

d = defaultdict(lambda : n)
cnt = 0
for i in range(x[-1]):
    if i >= x[cnt]:
        while i >= x[cnt]:
            cnt += 1
            
    d[i] = cnt

ans = []
for _ in range(int(input())):
    i = int(input())
    ans.append(d[i])
print(*ans, sep='\n')

要求二分实现一次,dp实现一次

binary search实现

python
import bisect

n = int(input())
x = [int(_) for _ in input().split()]
x.sort()

for _ in range(int(input())):
    m = int(input())
    print(bisect.bisect_right(x, m))

如果将此问题看作一个 dp 问题,其实这就变成了一个求累积和的问题,因为我们不仅需要知道小于等于某价格的店铺数量,而且还需要知道小于等于其他任何可能价格的店铺数量。每天我们都需要查询小于等于 mi 的店铺有多少个。

可以把所有价格进行排序然后使用 dp 保存每个价格以及之前所有价格的店铺总数量,也就是说 dp[i] = dp[i-1] + current_shop_number。然后就可以直接得出答案。

这就代表了在价格不大于 xi 的店铺中,可以购买 "Beecola" 的店铺数量。

python
n = int(input())
prices = sorted(list(map(int, input().split())))
q = int(input())
coins = [int(input()) for _ in range(q)]

# 创建DP数组并初始化
dp = [0] * 100001
for price in prices:
    dp[price] += 1
for i in range(1, len(dp)):
    dp[i] += dp[i-1]

# 处理并输出每一天的结果
for coin in coins:
    if coin >= len(dp):
        print(dp[-1])
    else:
        print(dp[coin])

DP实现

python
input()
x = [int(_) for _ in input().split()]
nm = max(x)
c = [0]*(nm+1)
for i in x:
    c[i] += 1
 
for i in range(2, nm+1):
    c[i] += c[i-1]
 
#ans = []
for _ in range(int(input())):
    m = int(input())
    if m > nm:
        print(c[nm])
    else:
        print(c[m])
    #ans.append(c[m])
  
#print('\n'.join(map(str,ans)))

2022/11/20 说明:CF706B. Interesting drink,可以用二分法AC。但是二分法不容易写对或者写简洁,我们统一下,都按照源码方式来写,这样可以避免错误。https://github.com/python/cpython/blob/main/Lib/bisect.py

这个题目虽然可以用bisect模块来完成,但是二分的写法是需要掌握的,有题目需要自己写二分,因为bisect模块满足不了要求。另外,这种双指针的策略,也是需要掌握的。

image-20221120150542188
python
n = int(input())
a = sorted(list(map(int,input().split())))
m = int(input())
for _ in range(m):
    x = int(input())
    lo = 0
    hi = len(a)
    while lo < hi:
        mid = (lo + hi) // 2
        if x < a[mid]:
            hi = mid
        else:
            lo = mid + 1
    print(lo)

2020fall-cs101, 成泽恺

706B 思路:暴力超时,用二分查找或者动态规划二分查找:一般二分查找会返回数的位置或者找不到,但这个题只需要找到价格中小于等于输入和大于等于输入的分界线即可,所以查找上界 left 和 right,在 while 循环中取 left>=mid 时right=mid-1,最后结果就是上界 right+1。

python
n = int(input())
shop = sorted(list(map(int,input().split())))
m = int(input())
for i in range(m):
    a = int(input())
    l = 0
    r = n-1
    while l<=r:
        mid = (l+r)//2
        if a < shop[mid]:
            r = mid-1
        elif a >= shop[mid]:
            l = mid + 1
    print(r+1)

2020fall-cs101, 黄旭

解题思路:这道题试了一下用 bisect库做,觉得挺方便的

Python
import bisect
input()
lt=sorted([int(i) for i in input().split()])
for i in range(int(input())):
    print(bisect.bisect(lt,int(input())))

2020fall-cs101, 邹京驰

思路:让区间[a,b]不断折半,且始终满足x[a] <= p < x[b] ;直到a = b – 1。 a就是我“刚好吃的起”的那个餐馆的位次,也即我吃得起的餐馆的总数量。binary search 也是第一次见。思考怎么实现时的第一反应:“这不就是高数里的闭区间套吗?”于是按自己的思路很快写出来了,并且一次submitAC. 很满意。

python
def search(t):
    a = 0
    b = n
    while a != b-1:
        temp = (a+b)//2
        if x[temp] > t: 
            b = temp
        else:
            a = temp
        
    return a

n = int(input())
x = [int(x) for x in input().split()] 
q = int(input()) 
x.sort() 
x.insert(0, 0) 

for i in range(q):     
    p = int(input())     
    if p >= x[n]:         
        print(n)     
    else:        
        print(search(p))