1. Concise problem statement
Given K zones, each with capacity Ci and quality Qi, and N = ΣCi students, each with skill Pj and weight wj. Assign each student to exactly one zone (respecting capacities) to maximize the total weight of students for whom Pj > Q (zone’s quality). Output for each student the index of their assigned zone.

2. Detailed editorial

Problem restated as a weighted assignment: we have N students and N slots (zone seats). A student j assigned to zone i yields profit wj if Pj > Qi, otherwise 0. Capacities Ci sum to N. We must fill every slot exactly once. We want the maximum total profit.

Observation: if a student cannot beat any zone’s quality, assigning him anywhere gives 0, so his placement doesn’t affect profit. If he can beat at least one zone, we’d rather use him for one of those zones to collect his weight.

This is isomorphic to the “scheduling with deadlines and profits” problem:

  - Each student is a “job” with profit = wj and deadline = the count of all available seats in zones with Q < Pj.
  - Each seat is a “time slot”. If we schedule the job by its deadline, we earn its profit.

The greedy algorithm for scheduling with deadlines and profits says:
 1. Sort jobs (students) by descending profit w.
 2. For each job in that order, attempt to schedule it in the latest available slot ≤ its deadline.
 3. If successful, we collect the profit; if no slot is free before the deadline, we skip it (or leave it for later zero-profit assignment).
 4. At the end, assign all unscheduled jobs into the remaining slots arbitrarily (they earn zero).

Mapping back to zones:
  - Sort students by w descending.
  - Sort zones by Q ascending.
  - For each student, find the zone with the largest Q < P that still has free capacity (this corresponds to the latest slot). If found, assign him there and decrement its capacity.
  - Otherwise, leave him unassigned for now.
  - After processing all students, fill unassigned students into any zones that still have capacity.

This runs in O(N·K) (K≤100, N≤16 000), which is fine.

3. C++ Solution
```cpp
#include <bits/stdc++.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;
};

struct Zone {
    int q, cap, id;
};

struct Student {
    int p, w, id;
};

int k;
int64_t total_n;
vector<Zone> zones;
vector<Student> students;

void read() {
    cin >> k;
    zones.resize(k);
    total_n = 0;
    for(int i = 0; i < k; i++) {
        cin >> zones[i].cap;
        total_n += zones[i].cap;
    }

    for(int i = 0; i < k; i++) {
        cin >> zones[i].q;
        zones[i].id = i;
    }

    students.resize(total_n);
    for(int i = 0; i < total_n; i++) {
        cin >> students[i].p;
    }

    for(int i = 0; i < total_n; i++) {
        cin >> students[i].w;
        students[i].id = i;
    }
}

void solve() {
    // A student qualifies for the All-Russian olympiad iff his level p exceeds
    // his zone's level q. To maximise total qualifying weight we greedily
    // process students by decreasing weight; sort zones by increasing level
    // and place each student into the highest-level zone that still has free
    // capacity and that he can beat (q < p). This keeps low-level zones free
    // for weaker students who can only qualify there. Any students left
    // unassigned are poured into whatever capacity remains, in zone order.

    sort(students.begin(), students.end(), [&](auto& a, auto& b) {
        return a.w > b.w;
    });

    sort(zones.begin(), zones.end(), [&](auto& a, auto& b) {
        return a.q < b.q;
    });

    vector<int> answer(total_n, -1);

    for(auto& st: students) {
        int best_zone = -1;
        for(int j = k - 1; j >= 0; j--) {
            if(zones[j].q < st.p && zones[j].cap > 0) {
                best_zone = j;
                break;
            }
        }

        if(best_zone != -1) {
            answer[st.id] = zones[best_zone].id + 1;
            zones[best_zone].cap--;
        }
    }

    int zi = 0;
    for(int i = 0; i < total_n; i++) {
        if(answer[i] == -1) {
            while(zi < k && zones[zi].cap == 0) {
                zi++;
            }

            answer[i] = zones[zi].id + 1;
            zones[zi].cap--;
        }
    }

    for(int i = 0; i < total_n; i++) {
        cout << answer[i] << (i + 1 < total_n ? ' ' : '\n');
    }
}

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 with detailed comments
```python
import sys
def main():
    data = sys.stdin.read().split()
    it = iter(data)
    K = int(next(it))

    # Read capacities and compute total number of students
    caps = [int(next(it)) for _ in range(K)]
    totalN = sum(caps)

    # Read zone qualities
    qs = [int(next(it)) for _ in range(K)]

    # Read student skills and weights
    ps = [int(next(it)) for _ in range(totalN)]
    ws = [int(next(it)) for _ in range(totalN)]

    # Build zone objects: (quality, remaining capacity, original index)
    zones = sorted([ [qs[i], caps[i], i] for i in range(K) ], key=lambda z: z[0])

    # Build student objects: (weight, skill, original index)
    students = sorted([ [ws[i], ps[i], i] for i in range(totalN) ],
                      key=lambda s: -s[0])  # descending weight

    # Placeholder for answers
    answer = [-1]*totalN

    # Greedy assignment: heavy students first
    for w, p, sid in students:
        # scan zones from highest quality down
        for j in range(K-1, -1, -1):
            q, cap, zid = zones[j]
            if q < p and cap > 0:
                answer[sid] = zid + 1
                zones[j][1] -= 1  # decrease capacity
                break

    # Fill leftovers
    zptr = 0
    for i in range(totalN):
        if answer[i] == -1:
            # find next zone with capacity
            while zones[zptr][1] == 0:
                zptr += 1
            answer[i] = zones[zptr][2] + 1
            zones[zptr][1] -= 1

    # Print results
    print(" ".join(map(str, answer)))

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

5. Compressed editorial
- Model as scheduling “jobs” (students) with profit w and deadline = total seats in zones with Q < P.
- Greedy: sort students by descending w. For each, place in the latest qualifying zone (highest Q < P) with remaining capacity.
- Leftover students go to any free slots. This maximizes the total weight of P>Q assignments.
