题意:
给出一个数组大小,这个数组里面所有的数范围从 1到100000,这个数组有这样一个规则,某个子区间内的所有数必须不相同,求按字典序最小输出这个数组。
解法:
贪心+优先队列
先把所有区间按前端进行排序,再按后端进行排序,进行遍历,每次把前面区间用过的数字但现在遍历的区间没覆盖的数存进优先队列中,然后再取出来用。
本人AC代码:
#include<bits/stdc++.h>
#include<queue>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
using namespace std;
struct node {
int l;
int r;
}edge[100005];
int cmp(node aa,node bb){
if(aa.l == bb.l){
return aa.r < bb.r;
}else {
return aa.l < bb.l;
}
}
int main() {
int t;
int ans[100005];
for(scanf("%d",&t); t; t--){
priority_queue<int, vector<int>, greater<int> > q;
int n,m;
scanf("%d%d", &n, &m);
rep(i,1,m){
scanf("%d%d",&edge[i].l, &edge[i].r);
}
sort(edge+1, edge+1+m, cmp);
rep(i,1,n){
q.push(i);
ans[i] = -1;
}
int ml = 1, mr = 1;
rep(i,1,m){
if(edge[i].l != edge[i+1].l || i == m){
rep(j,ml,edge[i].l-1){
if(ans[j] == -1){
ans[j] = 1;
}else{
q.push(ans[j]);
}
}
rep(j,mr,edge[i].r){
if(ans[j] == -1){
ans[j] = q.top();
q.pop();
}
}
ml = edge[i].l;
mr = max(mr, edge[i].r);
}
}
if(ans[1] == -1){
ans[1] = 1;
}
printf("%d",ans[1]);
rep(i,2,n){
if(ans[i] == -1){
ans[i] = 1;
}
printf(" %d",ans[i]);
}
printf("\n");
}
}