Assign Football Outfits
Autumn Tournament (2022)
Submission name: outfit.cpp
Problem summary
Assign every child a different outfit from 1 through N. Child i accepts exactly the outfit numbers in [Li,Ri]. Find any valid assignment or determine that none exists.
Input
N, followed by N interval endpoints Li Ri.
Output
NO, or YES followed by each child’s assigned outfit in input order.
Constraints
1 ≤ N ≤ 1000000; 1 ≤ Li ≤ Ri ≤ N.
Worked example
Original statement sample; constructive output may differ when any valid answer is accepted.
Input
4 1 3 2 4 3 4 2 2
Output
YES 1 3 4 2
Solution analysis
- Process outfit numbers from 1 to N. Sort children by their first acceptable outfit. Before assigning number x, insert every not-yet-considered child with Li≤x into a min-heap keyed by Ri.
- Assign x to the waiting child whose deadline Ri is smallest. If no child is waiting, nobody can use x. If the smallest deadline is already below x, that child can no longer be satisfied. Either situation makes a perfect assignment impossible. Store results by original child index.
- In the sample, outfit 1 goes to child1. At outfit2, child4 has deadline2 and must be chosen before child2. Then child2 receives3 and child3 receives4, producing 1 3 4 2.
Why it works
Suppose some valid completion gives current outfit x to another waiting child while the heap chooses child a with the earliest deadline. In that completion a gets a later outfit y. Swap their outfits: a accepts x, and the other child accepts y because its left endpoint is at most x≤y and its right endpoint is at least a’s right endpoint≥y. Thus the greedy choice preserves feasibility at every step.
Watch out. Keep original child indices after sorting. This is deadline ordering, not ordering by shortest interval. Any valid assignment is allowed; do not require the source’s exact sample permutation.
Commented C++17 solution
An independently written complete program with standard headers.
#include<algorithm>
#include<functional>
#include<iostream>
#include<queue>
#include<utility>
#include<vector>
using namespace std;
struct Child{
int left;
int right;
int index;
};
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin>>n;
vector<Child>children(n);
for(int i=0;i<n;i++){
cin>>children[i].left>>children[i].right;
children[i].index=i;
}
sort(children.begin(),children.end(),[](const Child&a,const Child&b){
return a.left<b.left;
});
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>waiting;
vector<int>assigned(n);
int next=0;
for(int outfit=1;outfit<=n;outfit++){
while(next<n&&children[next].left<=outfit){
waiting.push({children[next].right,children[next].index});
next++;
}
// The most urgent waiting child must receive this outfit.
if(waiting.empty()||waiting.top().first<outfit){
cout<<"NO\n";
return 0;
}
assigned[waiting.top().second]=outfit;
waiting.pop();
}
cout<<"YES\n";
for(int i=0;i<n;i++){
if(i>0){
cout<<' ';
}
cout<<assigned[i];
}
cout<<'\n';
}