<|instruction|>
Solve the below problem. The solution should start with an abridged problem statement. Then key observations. Then full solution based on the observations. Then C++ and Python implementations with comments.

521. "North-East"
Time limit per test: 0.5 second(s)
Memory limit: 262144 kilobytes
input: standard
output: standard

The popular music band of international fame "North-East" is coming to Berland! This news has spread all over the country, so numerous fans are now ready to rush and buy all the tickets!

At present the fans still don't know in which cities the band plans to give concerts. The only thing is known at the moment is that the band will visit several cities, and as their name says, they will strictly move north and east when going to the next city. In other words when the band moves from city i to city j, city j is always located northward and eastward of the city i.

It's also known that the tour is planned in such a way that the maximum possible number of cities will be visited. The musicians refuse to reveal other details. As you know, fans always get ready for the arrival of their idols, so they would appreciate any single detail about possible movements of their favorite musicians.

Your task is to help the fans and find two lists of cities — A and B. The first list A should contain the cities, which the band might visit during the tour. The second list B should contain the cities, which the band will have to visit for sure during the tour.

Input
The first line of input contains a single integer n (1 ≤ n ≤ 105) — amount of cities in the country. The following n lines contain coordinates of the cities. Each line contains a pair of integers xi, yi (-106 ≤ xi, yi ≤ 106) — the coordinates of the i-th city. Ox axis is directed west-to-east, and Oy axis — south-to-north. No two given cities will be located at the same point.

Output
Print the required list A to the first line of output and B to the second line. Each list should start with the amount of cities in it, followed by the indices of cities in increasing order. Cities are numbered from 1 to n.

Example(s)
sample input
sample output
5
3 2
1 1
5 5
2 3
4 4
5 1 2 3 4 5
3 2 3 5

sample input
sample output
5
1 1
10 10
5 6
10 1
6 5
4 1 2 3 5
2 1 2

<|response|>
1. Abridged problem statement  
You have n distinct points (cities) with integer coordinates (x, y). A “tour” is a sequence of cities in which both x and y strictly increase at each step. Let L be the maximum length of any such tour.  
• List A: all city indices that appear in at least one tour of length L.  
• List B: all city indices that appear in every tour of length L.  
Output A and B: each line begins with the list size, then the sorted indices.

2. Key observations  
- This is a 2D longest increasing subsequence (LIS) problem: we need the LIS ending at each point (up_dp) and the LIS starting from each point if we reverse the x-order (down_dp).  
- For each city i, up_dp[i] = length of longest increasing-both-coordinates path ending at i.  
- Similarly, down_dp[i] = length of longest path starting at i when we traverse cities by decreasing x (but still require increasing y).  
- If a city i lies on some maximum-length tour, then up_dp[i] + down_dp[i] − 1 = L.  
- Among those cities, at each “level” k = up_dp[i], if exactly one city has that level, it must be in every maximum tour at position k.

3. Full solution approach  
a) Coordinate compression on y:  
   • Collect all y values, sort uniquely, map each y to a rank in 1…M.  
b) Compute up_dp:  
   • Sort cities by x ascending; break ties arbitrarily (cities with equal x cannot follow each other).  
   • Maintain a Fenwick (BIT) over y-ranks for range-maximum queries.  
   • For each city in increasing x, query BIT for max over [1 … ry−1], set up_dp = 1 + that max, then update BIT at ry with up_dp.  
c) Compute down_dp:  
   • Now sort cities by x descending. We still want y strictly increasing; we can reuse the same BIT by mirroring y-ranks: mr = M+1 − ry, then querying prefix [1…mr−1].  
   • For each city in descending x, query BIT for max over [1 … mr−1], set down_dp = 1 + that max, then update BIT at mr.  
d) Let L = max_i (up_dp[i] + down_dp[i] − 1).  
e) Build List A = { i | up_dp[i] + down_dp[i] − 1 == L }.  
f) Group A by level k = up_dp[i]. For each k, if the group size is 1, that city is forced → add to B.  
g) Sort A and B and print.

Complexity: O(n log n) for sorting, coordinate compression, and BIT operations.

4. C++ implementation with detailed comments  
```cpp
#include <bits/stdc++.h>
using namespace std;

// Fenwick tree (BIT) supporting point-update (max) and prefix-max query
struct Fenwick {
    int n;
    vector<int> bit;
    Fenwick(int _n): n(_n), bit(n+1, 0) {}
    // update position i to max(bit[i], v)
    void update(int i, int v) {
        for(; i <= n; i += i & -i)
            bit[i] = max(bit[i], v);
    }
    // query max over [1..i]
    int query(int i) {
        int res = 0;
        for(; i > 0; i -= i & -i)
            res = max(res, bit[i]);
        return res;
    }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;
    vector<pair<long long,long long>> coord(n);
    for(int i = 0; i < n; i++)
        cin >> coord[i].first >> coord[i].second;

    // 1) Compress y-coordinates to ranks 1..M
    vector<long long> ys(n);
    for(int i = 0; i < n; i++) ys[i] = coord[i].second;
    sort(ys.begin(), ys.end());
    ys.erase(unique(ys.begin(), ys.end()), ys.end());
    int M = ys.size();

    // prepare points with (x, y_rank, original_index)
    struct P { long long x; int ry, id; };
    vector<P> pts(n);
    for(int i = 0; i < n; i++){
        int ry = int(lower_bound(ys.begin(), ys.end(), coord[i].second) - ys.begin()) + 1;
        pts[i] = { coord[i].first, ry, i+1 };
    }

    // 2) Compute up_dp: LIS ending at each point
    vector<int> up_dp(n+1, 0);
    sort(pts.begin(), pts.end(),
         [&](auto &a, auto &b){ return a.x < b.x; });
    Fenwick fw1(M);
    for(auto &p : pts) {
        // best among y < current y
        int best = fw1.query(p.ry - 1);
        up_dp[p.id] = best + 1;
        fw1.update(p.ry, up_dp[p.id]);
    }

    // 3) Compute down_dp: LIS starting at each point when x decreases
    vector<int> down_dp(n+1, 0);
    // mirror y-rank: mr = M+1 - ry
    for(auto &p : pts)
        p.ry = M + 1 - p.ry;
    sort(pts.begin(), pts.end(),
         [&](auto &a, auto &b){ return a.x > b.x; });
    Fenwick fw2(M);
    for(auto &p : pts) {
        int best = fw2.query(p.ry - 1);
        down_dp[p.id] = best + 1;
        fw2.update(p.ry, down_dp[p.id]);
    }

    // 4) Find global max L
    int L = 0;
    for(int i = 1; i <= n; i++)
        L = max(L, up_dp[i] + down_dp[i] - 1);

    // 5) Build List A
    vector<int> A;
    for(int i = 1; i <= n; i++)
        if(up_dp[i] + down_dp[i] - 1 == L)
            A.push_back(i);
    sort(A.begin(), A.end());

    // 6) Build List B: those levels with unique city
    // group A by level = up_dp[i]
    unordered_map<int, vector<int>> byLevel;
    byLevel.reserve(A.size());
    for(int i : A)
        byLevel[ up_dp[i] ].push_back(i);

    vector<int> B;
    for(auto &kv : byLevel) {
        if(kv.second.size() == 1)
            B.push_back(kv.second[0]);
    }
    sort(B.begin(), B.end());

    // 7) Output
    cout << A.size();
    for(int i : A) cout << ' ' << i;
    cout << "\n";
    cout << B.size();
    for(int i : B) cout << ' ' << i;
    cout << "\n";

    return 0;
}
```

5. Python implementation with detailed comments  
```python
import sys
input = sys.stdin.readline

# Fenwick tree for prefix maximum
class Fenwick:
    def __init__(self, n):
        self.n = n
        self.bit = [0] * (n+1)
    def update(self, i, v):
        while i <= self.n:
            if self.bit[i] < v:
                self.bit[i] = v
            i += i & -i
    def query(self, i):
        res = 0
        while i > 0:
            if self.bit[i] > res:
                res = self.bit[i]
            i -= i & -i
        return res

def main():
    n = int(input())
    pts = []
    ys = []
    for idx in range(1, n+1):
        x, y = map(int, input().split())
        pts.append([x, y, idx])
        ys.append(y)
    # compress y to 1..M
    ys_sorted = sorted(set(ys))
    M = len(ys_sorted)
    for p in pts:
        p.append( ys_sorted.index(p[1]) + 1 )  # p[3] = y_rank

    # up_dp: LIS ending at each city
    up_dp = [0]*(n+1)
    pts.sort(key=lambda p: (p[0], p[1]))
    fw1 = Fenwick(M)
    for x, y, idx, ry in pts:
        best = fw1.query(ry-1)
        up_dp[idx] = best + 1
        fw1.update(ry, up_dp[idx])

    # down_dp: LIS starting at city when x decreases
    # mirror ry to mr = M+1-ry for suffix→prefix trick
    for p in pts:
        p[3] = M + 1 - p[3]
    pts.sort(key=lambda p: -p[0])
    down_dp = [0]*(n+1)
    fw2 = Fenwick(M)
    for x, y, idx, mry in pts:
        best = fw2.query(mry-1)
        down_dp[idx] = best + 1
        fw2.update(mry, down_dp[idx])

    # compute L
    L = 0
    for i in range(1, n+1):
        L = max(L, up_dp[i] + down_dp[i] - 1)

    # List A: cities on some max-length path
    A = [i for i in range(1, n+1) if up_dp[i] + down_dp[i] - 1 == L]
    A.sort()

    # List B: those levels with unique city
    from collections import defaultdict
    bylev = defaultdict(list)
    for i in A:
        bylev[ up_dp[i] ].append(i)
    B = [v[0] for v in bylev.values() if len(v)==1]
    B.sort()

    # output
    print(len(A), *A)
    print(len(B), *B)

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

Explanation of steps is embedded as comments in the code. Both implementations run in O(n log n) time and O(n) memory, suitable for n up to 10^5.