Розбір
The interval will be called good if the numbers in it lie in the range inclusive (meaning ).
We implement a sliding window using two pointers and and maintain it so that the current interval is good, while the interval is bad.
For example, for the following sequence:
the intervals , and are good.
the intervals are bad.
If , extend the current interval to . Otherwise, reduce it to . Before moving the pointer , print the number of elements lying between and inclusive. It equals .
The algorithm’s complexity is linear, i.e. .
Example
Let’s consider the movement of pointers for the given example.
For the given condition , so we move the pointer forward.
Now . We need to move the pointer forward. However, before moving it, print the number of elements lying between and inclusive. It is equal to .
Move forward until .
Now . Print the answer for (it equals ) and increase by .
Algorithm realization
Read the input data.
scanf("%d", &n); for (i = 0; i < n; i++) scanf("%d", &a[i]);
Initialize the pointers .
i = j = 0;
Move the pointers forward until an answer is found for each value of .
while (i < n) // [i..j] {
If (and has not exceeded the array bounds, meaning ), extend the current interval by incrementing the pointer .
if ((j < n) && (a[j] <= 2 * a[i])) j++; else {
If , print the answer for index and increment by one.
printf("%d ", j - i); i++; } }
Algorithm realization — binary search, O(n log n)
Read the input data.
scanf("%d", &n); v.resize(n); for (i = 0; i < n; i++) scanf("%d", &v[i]);
For each index , using binary search, find the largest value of the index such that the numbers from to are contained in the interval , and . The count of numbers in the interval equals .
for (i = 0; i < n; i++) { x = upper_bound(v.begin(), v.end(), 2 * v[i]) - v.begin(); printf("%d ", x - i); }
Java realization
import java.util.*; public class Main { public static void main(String[] args) { Scanner con = new Scanner(System.in); int n = con.nextInt(); int m[] = new int[n]; for(int i = 0; i < n; i++) m[i] = con.nextInt(); int i = 0, j = 0; while (i < n) // [i..j] { if ((j < n) && (m[j] <= 2 * m[i])) j++; else { System.out.print(j - i + " "); i++; } } con.close(); } }
Python realization
Read the input data.
n = int(input()) lst = list(map(int,input().split()))
Initialize the pointers .
i = j = 0
Move the pointers forward until an answer is found for each value of .
while (i < n): # [i..j]
If (and has not exceeded the array bounds, meaning ), extend the current interval by incrementing the pointer .
if (j < n and lst[j] <= 2 * lst[i]): j += 1 else:
If , print the answer for index and increment by one.
print(j - i, end=" "); i += 1
Python realization — binary search, O(n log n)
from bisect import bisect_right
Read the input data.
n = int(input()) v = list(map(int, input().split()))
For each index , using binary search, find the largest value of the index such that the numbers from to are contained in the interval , and . The count of numbers in the interval equals .
for i in range(n): x = bisect_right(v, 2 * v[i]) print(x - i, end=" ")