## 1) Abridged problem statement

Maintain a multiset of segments \([L, R]\) on the number line under a stream of queries:

- `+ L R`: add segment \([L, R]\) and **print** how many currently active segments \([l, r]\) satisfy \(L \le l\) and \(r \le R\) (i.e., are inside the new segment, endpoints allowed).
- `- L R`: remove **one** occurrence of segment \([L, R]\) if it exists; otherwise ignore.

Constraints: up to \(250{,}000\) queries, coordinates in \([-10^9,10^9]\), and **at most 1000 segments are active at any time**.

---

## 2) Detailed Editorial

### Key observation
Although there can be many queries, the number of **active** segments at any moment is small: \(\le 1000\).
So for each `+` query, we can simply scan all currently active segments and count those contained in the new one.

That yields:

- `+`: \(O(A)\) where \(A \le 1000\)
- `-`: remove one matching segment from the active set; can also be \(O(A)\)

Total worst-case operations: \(250{,}000 \times 1000 = 250\) million checks, which is feasible in optimized C++ (and this solution further accelerates scanning using AVX2 SIMD).

### What must be counted
For a new segment \([L, R]\), an active segment \([l, r]\) is inside iff:
\[
l \ge L \quad \text{and} \quad r \le R
\]
Non-strict containment includes equality.

### Handling deletions with duplicates
There can be multiple identical segments. Deletion `- L R` removes only **one** copy.
We therefore store active segments as parallel arrays and, when deleting, remove just one matching element.

Efficient "remove by swap with last" technique:
- Find an index `i` where the segment equals \((L,R)\)
- Replace it with the last segment
- Pop back

This makes deletion \(O(A)\) for search, but \(O(1)\) for the actual removal without shifting.

### Why coordinate compression appears in the code
The provided code compresses all endpoints from all processed queries to small integers \([1..M]\). This is **not required** for correctness for the brute-force method (comparisons on original ints are fine), but it:
- keeps values in 32-bit range comfortably
- is convenient for SIMD comparisons (using 32-bit lanes)
- avoids any chance of overflow when doing small offset tricks like comparing with `ql-1` and `qr+1`

Compression steps:
1. Read all queries.
2. Collect all `L` and `R` values that appear.
3. Sort unique coordinates.
4. Replace each endpoint by its rank (1-indexed).

Since compression preserves order, comparisons like \(l \ge L\) and \(r \le R\) remain valid.

### SIMD acceleration (AVX2) in the scan
To count contained segments fast, the code processes 8 segments at a time using 256-bit registers:

For each batch of 8:
- Load 8 `l` values and 8 `r` values
- Compare `l >= L` and `r <= R` via vector comparisons (using the `>` trick: `l >= L` is `l > L-1`, `r <= R` is `R+1 > r`)
- Combine masks, count how many lanes matched

This reduces the constant factor substantially. (An alternative `O(Q log^2 Q)` data-structure approach with a segment tree over `L` and an inner ordered structure over `R` is described in the code comment, but the brute force with the small active-set bound is simpler and fast enough here.)

### Complexity
Let \(A\) be the maximum active segments (≤ 1000), \(Q\) queries (≤ 250k).

- Each `+`: \(O(A)\) checks (vectorized, effectively faster)
- Each `-`: \(O(A)\) search, then \(O(1)\) swap-pop

Total: \(O(Q \cdot A)\) worst-case, but with small \(A\), passes.

---

## 3) C++ Solution

```cpp
#include <bits/stdc++.h>
#include <immintrin.h>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
}

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

vector<tuple<bool, int, int>> queries;

void read() {
    char type;
    int l, r;
    multiset<pair<int, int>> segments;
    vector<int> all_coords;
    while(cin >> type >> l >> r) {
        if(type == '+') {
            segments.insert({l, r});
            queries.push_back({true, l, r});
        } else {
            auto it = segments.find({l, r});
            if(it == segments.end()) {
                continue;
            }
            segments.erase(it);
            queries.push_back({false, l, r});
        }

        all_coords.push_back(l);
        all_coords.push_back(r);
    }

    sort(all_coords.begin(), all_coords.end());
    all_coords.erase(
        unique(all_coords.begin(), all_coords.end()), all_coords.end()
    );

    for(auto& [add, l, r]: queries) {
        l = (int)(lower_bound(all_coords.begin(), all_coords.end(), l) -
                  all_coords.begin() + 1);
        r = (int)(lower_bound(all_coords.begin(), all_coords.end(), r) -
                  all_coords.begin() + 1);
    }
}

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2")

class ActiveSegments {
  private:
    vector<int> Ls;
    vector<int> Rs;

  public:
    ActiveSegments() {
        Ls.reserve(1024);
        Rs.reserve(1024);
    }

    void add(int l, int r) {
        Ls.push_back(l);
        Rs.push_back(r);
    }

    bool remove(int ql, int qr) {
        size_t n = Ls.size();
        size_t i = 0;

        __m256i qlv = _mm256_set1_epi32(ql);
        __m256i qrv = _mm256_set1_epi32(qr);

        for(; i + 7 < n; i += 8) {
            __m256i lv = _mm256_loadu_si256((const __m256i*)(Ls.data() + i));
            __m256i rv = _mm256_loadu_si256((const __m256i*)(Rs.data() + i));

            __m256i matchL = _mm256_cmpeq_epi32(lv, qlv);
            __m256i matchR = _mm256_cmpeq_epi32(rv, qrv);
            __m256i both = _mm256_and_si256(matchL, matchR);

            int mask = _mm256_movemask_epi8(both);
            if(mask != 0) {
                int bit = __builtin_ctz(mask);
                size_t lane = bit >> 2;
                size_t pos = i + lane;

                Ls[pos] = Ls.back();
                Ls.pop_back();
                Rs[pos] = Rs.back();
                Rs.pop_back();
                return true;
            }
        }

        for(; i < n; ++i) {
            if(Ls[i] == ql && Rs[i] == qr) {
                Ls[i] = Ls.back();
                Ls.pop_back();
                Rs[i] = Rs.back();
                Rs.pop_back();
                return true;
            }
        }
        return false;
    }

    int count_contained(int ql, int qr) const {
        int cnt = 0;
        size_t n = Ls.size();
        size_t i = 0;

        __m256i qlv = _mm256_set1_epi32(ql - 1);
        __m256i qrv = _mm256_set1_epi32(qr + 1);

        for(; i + 7 < n; i += 8) {
            __m256i lv = _mm256_loadu_si256((const __m256i*)&Ls[i]);
            __m256i rv = _mm256_loadu_si256((const __m256i*)&Rs[i]);

            __m256i ge = _mm256_cmpgt_epi32(lv, qlv);
            __m256i le = _mm256_cmpgt_epi32(qrv, rv);

            __m256i both = _mm256_and_si256(ge, le);

            int mask = _mm256_movemask_epi8(both);
            cnt += __builtin_popcount(mask) >> 2;
        }

        for(; i < n; ++i) {
            if(Ls[i] >= ql && Rs[i] <= qr) {
                ++cnt;
            }
        }

        return cnt;
    }
};

void solve() {
    // One approach for solving this in O(Q log^2 Q) is to build a segment tree
    // on the L coordinates, and then keep all R coordinates in a sorted manner.
    // Then the update (addition / removal), ends up being a walk down to the
    // corresponding leaf of the segment tree for L, and inserting / erasing R
    // from all nodes we visit. The query ends up being just decomposing the [L;
    // R] range with the O(log Q) segment tree nodes, and figuring out how many
    // R coordinates fall within [L; R]. For the inner structure we can use some
    // BST or offline build all unique values that could appear in the segment
    // tree node, and do a segment tree / BIT over them. One easy approach is
    // to use the Policy-Based Data Structures (PBDS) from GNU C++ which is
    // widely accepted on online judges. Another simple approach that ends up
    // being fast in practice is to implement everything with a 2D fenwick tree,
    // by keeping the nodes as an unordered_map. However, after trying to
    // implement this it's a bit hard to fit in the memory limit.
    //
    // Instead, here we will use the fact that there are at most ~1000-2000
    // active segments at any moment and do a brute-force with a vector. This is
    // fast enough to pass, but we can further speed it up with AVX2 SIMD.

    ActiveSegments active;

    for(auto [is_add, l, r]: queries) {
        if(is_add) {
            int cnt = active.count_contained(l, r);
            cout << cnt << '\n';
            active.add(l, r);
        } else {
            active.remove(l, r);
        }
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        // cout << "Case #" << test << ": ";
        solve();
    }
    return 0;
}
```

---

## 4) Python solution (same idea, detailed comments)

```python
import sys

def solve() -> None:
    # Read all lines (queries until EOF)
    lines = sys.stdin.buffer.read().splitlines()

    queries = []          # list of (is_add: bool, L: int, R: int)
    coords = []           # endpoints for coordinate compression

    # To ignore invalid deletions, we need to know what segments are present
    # while reading. In Python, we can use a dict counting occurrences.
    present = {}  # (L,R) -> count

    for line in lines:
        if not line:
            continue
        t, ls, rs = line.split()
        L = int(ls)
        R = int(rs)

        if t == b'+':
            present[(L, R)] = present.get((L, R), 0) + 1
            queries.append((True, L, R))
            coords.append(L); coords.append(R)
        else:
            # Deletion: only keep this query if segment exists
            c = present.get((L, R), 0)
            if c == 0:
                continue
            if c == 1:
                del present[(L, R)]
            else:
                present[(L, R)] = c - 1

            queries.append((False, L, R))
            coords.append(L); coords.append(R)

    # Coordinate compression (optional for Python correctness, but matches C++)
    coords = sorted(set(coords))
    def comp(x: int) -> int:
        # 1-indexed compressed coordinate
        # Using binary search from bisect
        import bisect
        return bisect.bisect_left(coords, x) + 1

    queries = [(is_add, comp(L), comp(R)) for (is_add, L, R) in queries]

    # Active segments stored in two parallel lists.
    # We'll remove by swapping with last.
    Ls = []
    Rs = []

    out_lines = []

    for is_add, L, R in queries:
        if is_add:
            # Count how many active segments are contained in [L, R]
            cnt = 0
            # A <= 1000, so linear scan is fine
            for l, r in zip(Ls, Rs):
                if l >= L and r <= R:
                    cnt += 1
            out_lines.append(str(cnt))

            # Add the new segment
            Ls.append(L)
            Rs.append(R)
        else:
            # Remove one occurrence of (L, R) if present
            # Linear search, then swap with last for O(1) removal.
            n = len(Ls)
            for i in range(n):
                if Ls[i] == L and Rs[i] == R:
                    # swap-with-last
                    Ls[i] = Ls[-1]
                    Rs[i] = Rs[-1]
                    Ls.pop()
                    Rs.pop()
                    break

    sys.stdout.write("\n".join(out_lines))

if __name__ == "__main__":
    solve()
```

---

## 5) Compressed editorial

Since at most 1000 segments are active at any time, we can process `+ L R` by scanning all active segments and counting those with `l >= L && r <= R`, then insert the new segment. For `- L R`, remove one matching occurrence if present, using "swap with last + pop" for O(1) deletion after an O(A) search. Total time is \(O(Q \cdot A)\) with \(A \le 1000\), which fits easily; the C++ code additionally vectorizes scans with AVX2 to speed up constant factors.
