CF 1062473 - Advertising
The problem describes a shop that wants to choose one pack size a. Every customer wants to buy some amount of cans between l and r. A customer first takes as many full packs of size a as possible.
Rating: -
Tags: -
Solve time: 34s
Verified: yes
Solution
Problem Understanding
The problem describes a shop that wants to choose one pack size a. Every customer wants to buy some amount of cans between l and r. A customer first takes as many full packs of size a as possible. If the remaining cans are at least half of a pack, the customer also buys one extra full pack instead of buying the leftover cans separately.
The task is to decide whether there exists some pack size a such that every possible customer amount in the interval [l, r] ends up buying strictly more cans than they originally wanted.
The important observation is that a chosen pack size only needs to make the interval of possible purchases land inside the "round up" region of the pack. The values of l and r can be as large as 10^9, so checking every possible pack size is impossible. Even a loop over all values up to r would take too many operations in the worst case. With up to thousands of test cases, the solution needs to work in constant time or close to it.
The tricky part is understanding the boundary. If the customer wants exactly a multiple of a, they already bought the exact amount and cannot be forced to buy more. Also, if the leftover part is less than half of the pack, the customer keeps the original number of cans. A careless solution might only check one endpoint of the interval and miss that another value inside the interval behaves differently.
For example, consider:
1
1 2
The correct answer is:
NO
Trying a = 2 looks promising because a customer buying 2 cans fills a pack. However, a customer buying 1 can has a remainder of 1, and since it is not strictly enough to trigger the extra pack in the intended way, they do not buy more. The smallest possible intervals need special attention.
Another example:
1
3 4
The correct answer is:
YES
Choosing a = 5 works. A customer buying 3 cans has remainder 3, and a customer buying 4 cans has remainder 4. Both remainders are at least half of the pack, so both customers take the full pack and buy more.
Approaches
The direct approach is to try every possible pack size a and test whether every value from l to r becomes larger after the customer's decision. For a fixed a, we can simulate the customer behavior for every possible purchase amount. This is correct because it checks the exact condition required by the problem.
The problem is the number of checks. The interval length can be as large as 10^9, and the possible pack sizes can also be very large. A brute force solution could require around 10^18 checks in the worst case, which is far beyond what can run in time.
The key insight comes from rewriting the condition. For a value x to increase after choosing pack size a, the value x must lie in the second half of some block of length a. The first half of every block fails because the customer keeps the original amount. The second half succeeds because the leftover is large enough to make the customer take one more pack.
For a fixed a, every successful range has the form:
[a / 2, a - 1] relative to each block of size a
The easiest way to guarantee that all numbers from l to r are successful is to choose a pack size a that is larger than twice the left boundary. If a = 2 * l, then the first successful region begins exactly at l, and all values before the end of the first pack can be covered. The only requirement is that the right boundary does not reach the end of the pack.
This reduces the question to checking whether there exists a value a where:
2 * l <= a
and
r < a
Such a value exists exactly when r < 2 * l. This single comparison is enough for every test case.
| Approach | Time Complexity | Space Complexity | Verdict |
|---|---|---|---|
| Brute Force | O((r-l+1) * r) | O(1) | Too slow |
| Optimal | O(1) | O(1) | Accepted |
Algorithm Walkthrough
- Read the interval
[l, r]representing all possible customer purchases. - Compare
rwith2 * l. The reason for this comparison is that the pack size must be large enough to makelthe beginning of the profitable half of a pack, but it must also be larger than every value in the interval so that no customer hits an exact pack boundary. - If
r < 2 * l, printYES. Otherwise, printNO.
Why it works: when r < 2 * l, choosing a = 2 * l makes every number from l to r fall before the end of the first pack and inside the region where the leftover is at least half of the pack. Every customer buys one extra pack. If r >= 2 * l, any pack large enough to help l will have a boundary reached by some value in the interval, and that value will not increase.
Python Solution
import sys
input = sys.stdin.readline
def solve():
t = int(input())
ans = []
for _ in range(t):
l, r = map(int, input().split())
if r < 2 * l:
ans.append("YES")
else:
ans.append("NO")
print("\n".join(ans))
if __name__ == "__main__":
solve()
The solution only needs to store the answers for printing. The comparison uses 2 * l, and Python integers handle these values safely.
The condition directly implements the mathematical observation from the algorithm. There is no simulation, no loops over the interval, and no need to construct the pack size itself.
The boundary condition uses a strict inequality. If r == 2 * l, the interval reaches the exact point where a customer can fail, so the answer must be NO.
Worked Examples
Sample 1
Input:
3
3 4
1 2
120 150
Trace:
| l | r | 2*l | Check | Answer |
|---|---|---|---|---|
| 3 | 4 | 6 | 4 < 6 | YES |
| 1 | 2 | 2 | 2 < 2 is false | NO |
| 120 | 150 | 240 | 150 < 240 | YES |
The first and third cases have intervals completely inside a profitable part of a possible pack. The second case touches the boundary and fails.
Custom Trace
Input:
1
5 9
Trace:
| l | r | 2*l | Check | Answer |
|---|---|---|---|---|
| 5 | 9 | 10 | 9 < 10 | YES |
Choosing a = 10 works. The possible purchases are all from 5 to 9, which are all in the second half of a pack of size 10.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(t) | Each test case performs one arithmetic comparison |
| Space | O(t) | The output list stores one answer per test case |
The constraints allow this easily because even thousands of test cases only require a few thousand operations.
Test Cases
import sys, io
def solve_data(data):
sys.stdin = io.StringIO(data)
input = sys.stdin.readline
t = int(input())
res = []
for _ in range(t):
l, r = map(int, input().split())
res.append("YES" if r < 2 * l else "NO")
return "\n".join(res)
# provided samples
assert solve_data("""3
3 4
1 2
120 150
""") == """YES
NO
YES"""
# minimum size
assert solve_data("""1
1 1
""") == "YES"
# boundary where answer changes
assert solve_data("""2
5 9
5 10
""") == """YES
NO"""
# large values
assert solve_data("""1
500000000 999999999
""") == "YES"
# all values in a narrow failing range
assert solve_data("""1
100 200
""") == "NO"
| Test input | Expected output | What it validates |
|---|---|---|
1 1 |
YES | Checks the smallest possible interval |
5 9 |
YES | Confirms a range just below the critical boundary |
5 10 |
NO | Catches the strict inequality error |
| Large interval | YES | Confirms large values are handled without iteration |
100 200 |
NO | Tests an interval that reaches a failing boundary |
Edge Cases
For the interval:
1
1 2
the algorithm computes 2 * l = 2. Since r is not smaller than 2, it returns NO. The reason is that any pack size large enough to help the customer buying one can also have the customer buying two land exactly on a pack boundary.
For the interval:
1
3 4
the algorithm computes 2 * l = 6. Since 4 < 6, it returns YES. A valid pack size is 6, where both possible purchases have leftovers large enough to trigger buying the full pack.
For a large boundary case:
1
100000000 200000000
the algorithm does not iterate through any values. It only checks whether 200000000 < 200000000, which is false, so it returns NO. This demonstrates why the comparison must be strict and why the constant time solution handles maximum values safely.