开始往线段树上想,死活想不出来,最后队友往队列上想,遇到了瓶颈,最后半个小时给我说的思路。突然明白,然后比赛写错个地方,来不及了,赛后改的
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <queue> using namespace std; const int maxn=1e5+10; bool vis[maxn]; int a[maxn]; struct note { int l,r; int flag; bool operator <(const note &p) const { return (l<p.l)||(l==p.l&&r>p.r); } }aa[maxn]; int t; int n,m; priority_queue<int,vector<int>,greater<int> > q; int main() { scanf("%d",&t); while(t--) { while(q.size()) q.pop();//从里面取最小的数填充队列 scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&aa[i].l,&aa[i].r); } sort(aa+1,aa+1+m); for(int i=1;i<=n;i++) { q.push(i); a[i]=1; vis[i]=1; } if(m==0) { for(int i=1;i<=n;i++) { if(i!=1) printf(" "); printf("%d",a[i]); } } else { int l=aa[1].l; int r=aa[1].r; for(int i=aa[1].l;i<=aa[1].r;i++) { int v=q.top(); q.pop();//填充 vis[v]=0;//队列里是否存在v a[i]=v; } for(int i=2;i<=m;i++) { if(aa[i].l>=l&&aa[i].r<=r) continue; for(int j=l;j<aa[i].l;j++) if(!vis[a[j]]) { q.push(a[j]);//上一个l到这一个l之间的数可以再用,入队 vis[a[j]]=1; } for(int j=max(r+1,aa[i].l);j<=aa[i].r;j++)//两个区间相交则从r+1开始填充,否则从aa[i].l开始填充 { int v=q.top(); q.pop(); vis[v]=0; a[j]=v; } l=aa[i].l; r=aa[i].r; } for(int i=1;i<=n;i++) { if(i!=1) printf(" "); printf("%d",a[i]); } } printf("\n"); } return 0; }