Fixed Point Removal (Codeforces 1405E)
Tags: Others, binary search

Let $$$a_1, \ldots, a_n$$$ be an array of $$$n$$$ positive integers. In one operation, you can choose an index $$$i$$$ such that $$$a_i = i$$$, and remove $$$a_i$$$ from the array (after the removal, the remaining parts are concatenated).The weight of $$$a$$$ is defined as the maximum number of elements you can remove.You must answer $$$q$$$ independent queries $$$(x, y)$$$: after replacing the $$$x$$$ first elements of $$$a$$$ and the $$$y$$$ last elements of $$$a$$$ by $$$n+1$$$ (making them impossible to remove), what would be the weight of $$$a$$$?

Input: The first line contains two integers $$$n$$$ and $$$q$$$ ($$$1 \le n, q \le 3 \cdot 10^5$$$)  — the length of the array and the number of queries.The second line contains $$$n$$$ integers $$$a_1$$$, $$$a_2$$$, ..., $$$a_n$$$ ($$$1 \leq a_i \leq n$$$) — elements of the array.The $$$i$$$-th of the next $$$q$$$ lines contains two integers $$$x$$$ and $$$y$$$ ($$$x, y \ge 0$$$ and $$$x+y < n$$$).

Output: Print $$$q$$$ lines, $$$i$$$-th line should contain a single integer  — the answer to the $$$i$$$-th query.

Note: Explanation of the first query:After making first $$$x = 3$$$ and last $$$y = 1$$$ elements impossible to remove, $$$a$$$ becomes $$$[\times, \times, \times, 9, 5, 4, 6, 5, 7, 8, 3, 11, \times]$$$ (we represent $$$14$$$ as $$$\times$$$ for clarity).Here is a strategy that removes $$$5$$$ elements (the element removed is colored in red):  $$$[\times, \times, \times, 9, \color{red}{5}, 4, 6, 5, 7, 8, 3, 11, \times]$$$  $$$[\times, \times, \times, 9, 4, 6, 5, 7, 8, 3, \color{red}{11}, \times]$$$  $$$[\times, \times, \times, 9, 4, \color{red}{6}, 5, 7, 8, 3, \times]$$$  $$$[\times, \times, \times, 9, 4, 5, 7, \color{red}{8}, 3, \times]$$$  $$$[\times, \times, \times, 9, 4, 5, \color{red}{7}, 3, \times]$$$  $$$[\times, \times, \times, 9, 4, 5, 3, \times]$$$ (final state) It is impossible to remove more than $$$5$$$ elements, hence the weight is $$$5$$$.

Sample Inputs:
13 5
2 2 3 9 5 4 6 5 7 8 3 11 13
3 1
0 0
2 4
5 0
0 12

5 2
1 4 1 2 4
0 0
1 0

Sample Outputs:
5
11
6
1
0

2
0

Solution (Python):
from sys import stdin

def bitadd(a, w, bit):
    x = a
    while x <= len(bit) - 1:
        bit[x] += w
        x += x & -1 * x

def bitsum(a, bit):
    ret = 0
    x = a
    while x > 0:
        ret += bit[x]
        x -= x & -1 * x
    return ret

class RangeBIT:

    def __init__(self, N, indexed):
        self.bit1 = [0] * (N + 2)
        self.bit2 = [0] * (N + 2)
        self.mode = indexed

    def bitadd(self, a, w, bit):
        x = a
        while x <= len(bit) - 1:
            bit[x] += w
            x += x & -1 * x

    def bitsum(self, a, bit):
        ret = 0
        x = a
        while x > 0:
            ret += bit[x]
            x -= x & -1 * x
        return ret

    def add(self, l, r, w):
        l = l + (1 - self.mode)
        r = r + (1 - self.mode)
        self.bitadd(l, -1 * w * l, self.bit1)
        self.bitadd(r, w * r, self.bit1)
        self.bitadd(l, w, self.bit2)
        self.bitadd(r, -1 * w, self.bit2)

    def sum(self, l, r):
        l = l + (1 - self.mode)
        r = r + (1 - self.mode)
        ret = self.bitsum(r, self.bit1) + r * self.bitsum(r, self.bit2)
        ret -= self.bitsum(l, self.bit1) + l * self.bitsum(l, self.bit2)
        return ret
(n, q) = map(int, stdin.readline().split())
a = list(map(int, stdin.readline().split()))
qs = [[] for i in range(n + 1)]
ans = [None] * q
BIT = [0] * (n + 1)
for loop in range(q):
    (x, y) = map(int, stdin.readline().split())
    l = x + 1
    r = n - y
    qs[r].append((l, loop))
for r in range(1, n + 1):
    b = r - a[r - 1]
    if b >= 0:
        L = 1
        R = r + 1
        while R - L != 1:
            M = (L + R) // 2
            if bitsum(M, BIT) >= b:
                L = M
            else:
                R = M
        if bitsum(L, BIT) >= b:
            bitadd(1, 1, BIT)
            bitadd(L + 1, -1, BIT)
    for (ql, qind) in qs[r]:
        ans[qind] = bitsum(ql, BIT)
for i in ans:
    print(i)

Solution (Python):
from sys import stdin

def bitadd(a, w, bit):
    x = a
    while x <= len(bit) - 1:
        bit[x] += w
        x += x & -1 * x

def bitsum(a, bit):
    ret = 0
    x = a
    while x > 0:
        ret += bit[x]
        x -= x & -1 * x
    return ret

class RangeBIT:

    def __init__(self, N, indexed):
        self.bit1 = [0] * (N + 2)
        self.bit2 = [0] * (N + 2)
        self.mode = indexed

    def bitadd(self, a, w, bit):
        x = a
        while x <= len(bit) - 1:
            bit[x] += w
            x += x & -1 * x

    def bitsum(self, a, bit):
        ret = 0
        x = a
        while x > 0:
            ret += bit[x]
            x -= x & -1 * x
        return ret

    def add(self, l, r, w):
        l = l + (1 - self.mode)
        r = r + (1 - self.mode)
        self.bitadd(l, -1 * w * l, self.bit1)
        self.bitadd(r, w * r, self.bit1)
        self.bitadd(l, w, self.bit2)
        self.bitadd(r, -1 * w, self.bit2)

    def sum(self, l, r):
        l = l + (1 - self.mode)
        r = r + (1 - self.mode)
        ret = self.bitsum(r, self.bit1) + r * self.bitsum(r, self.bit2)
        ret -= self.bitsum(l, self.bit1) + l * self.bitsum(l, self.bit2)
        return ret
(n, q) = map(int, stdin.readline().split())
a = list(map(int, stdin.readline().split()))
qs = [[] for i in range(n + 1)]
ans = [None] * q
BIT = [0] * (n + 1)
for loop in range(q):
    (x, y) = map(int, stdin.readline().split())
    l = x + 1
    r = n - y
    qs[r].append((l, loop))
for r in range(1, n + 1):
    b = r - a[r - 1]
    if b >= 0:
        L = 1
        R = r + 1
        while R - L != 1:
            M = (L + R) // 2
            if bitsum(M, BIT) >= b:
                L = M
            else:
                R = M
        if bitsum(L, BIT) >= b:
            bitadd(1, 1, BIT)
            bitadd(L + 1, -1, BIT)
    for (ql, qind) in qs[r]:
        ans[qind] = bitsum(ql, BIT)
for i in ans:
    print(i)

Solution (Python):
from sys import stdin

def bitadd(a, w, bit):
    x = a
    while x <= len(bit) - 1:
        bit[x] += w
        x += x & -1 * x

def bitsum(a, bit):
    ret = 0
    x = a
    while x > 0:
        ret += bit[x]
        x -= x & -1 * x
    return ret

class RangeBIT:

    def __init__(self, N, indexed):
        self.bit1 = [0] * (N + 2)
        self.bit2 = [0] * (N + 2)
        self.mode = indexed

    def bitadd(self, a, w, bit):
        x = a
        while x <= len(bit) - 1:
            bit[x] += w
            x += x & -1 * x

    def bitsum(self, a, bit):
        ret = 0
        x = a
        while x > 0:
            ret += bit[x]
            x -= x & -1 * x
        return ret

    def add(self, l, r, w):
        l = l + (1 - self.mode)
        r = r + (1 - self.mode)
        self.bitadd(l, -1 * w * l, self.bit1)
        self.bitadd(r, w * r, self.bit1)
        self.bitadd(l, w, self.bit2)
        self.bitadd(r, -1 * w, self.bit2)

    def sum(self, l, r):
        l = l + (1 - self.mode)
        r = r + (1 - self.mode)
        ret = self.bitsum(r, self.bit1) + r * self.bitsum(r, self.bit2)
        ret -= self.bitsum(l, self.bit1) + l * self.bitsum(l, self.bit2)
        return ret
(n, q) = map(int, stdin.readline().split())
a = list(map(int, stdin.readline().split()))
qs = [[] for i in range(n + 1)]
ans = [None] * q
for loop in range(q):
    (x, y) = map(int, stdin.readline().split())
    l = x + 1
    r = n - y
    qs[r].append((l, loop))
BIT = [0] * (n + 1)
for r in range(1, n + 1):
    b = r - a[r - 1]
    if b >= 0:
        L = 1
        R = r + 1
        while R - L != 1:
            M = (L + R) // 2
            if bitsum(M, BIT) >= b:
                L = M
            else:
                R = M
        if bitsum(L, BIT) >= b:
            bitadd(1, 1, BIT)
            bitadd(L + 1, -1, BIT)
    for (ql, qind) in qs[r]:
        ans[qind] = bitsum(ql, BIT)
for i in ans:
    print(i)