hdu 6301 Distinct Values (思维+set)
hdu 6301 Distinct Values
题意:
给你m个区间,让你求出一个长度为n的区间且满足在这些区间的数不重复,
并且要求字典序最小
思路:
如果我们已经求出这个序列了,你会发现,如果大的区间已经满足条件了,
那么它包含的小区间也已经满足了。
然后它要求字典序最小,这个从左往右去填充就行了,每次都有能取的最小的
数去填充进去,这样形成的序列自然符合
所以我们需要一个容器来存储能用的数,假设我们处理完i这个位置,要过度到下一个,
如果i+1还在这个区间还好,如果不在,那么我们就要更新这个容器了,因为此时它
可以选择的数有更多。而我们要增加的数,就是上一个区间与这个区间没有交集的地方
,即两个区间最左端点的刚刚加进去的数。
具体注释看代码。
代码:
#include<bits/stdc++.h> using namespace std; int T; int n,m; #define N 100005 typedef pair<int,int> PII; #define fi first #define se second PII ipt[N]; int ans[N]; int pre[N]; int main() { scanf("%d",&T); while(T--) { scanf("%d %d",&n,&m); //初始化 for(int i=0;i<=n;i++) { pre[i]=i; ans[i]=1; } //pre记录每个最大区间的左端点 for(int i=1;i<=m;i++) { scanf("%d %d",&ipt[i].fi,&ipt[i].se); pre[ipt[i].se]=min(pre[ipt[i].se],ipt[i].fi); } //把那些零散的点也用包含它的最大区间包括进去 for(int i=n-1;i>=1;i--) { if(pre[i]>pre[i+1]) pre[i]=pre[i+1]; } set<int>mu; mu.clear(); for(int i=1;i<=n;i++) mu.insert(i); for(int i=1;i<=n;i++)//给每个位置赋值 { for(int j=pre[i-1];j<pre[i];j++)//更新目标集合 { mu.insert(ans[j]); } ans[i]=*mu.begin(); mu.erase(mu.begin()); } for(int i=1;i<=n;i++) { printf("%d%c",ans[i],i==n?'\n':' '); } } return 0; }