[HDU6301]Distinct Values【模拟】
6301 Distinct Values
这题是因为实在没事干了,我就随意打了一下,结果就A掉了。
想法很简单,用堆维护在这个区间没有出现过最小数(因为我们要字典序最小,肯定要越高位越小,所以肯定先放小的数),我们可以将区间全部投射到一维的数组上,然后枚举这个位置,肯定选择最大的这个覆盖区间,放置这个区间中没有的最小的数。
然后我们考虑区间转移,比如说当前区间结束了,那么当前区间的左边界到下一区间的左边界上的点肯定不会对当前造成影响,所以完全可以选择这段区间里的数。放到小根堆中就可以了。
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int T,n,m,Len,hep_Num[100005],Len_Num,Len_L,que[100005];
bool hsh[100005];
struct xcw{
int x,id;bool f;
bool operator <(const xcw b)const{return x<b.x;}
}a[200005],hep_L[200005];
int read(){
int ret=0;char ch=getchar();bool f=1;
for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');
for(; isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;
return f?ret:-ret;
}
void put_Num(int x){
hep_Num[++Len_Num]=-x;
push_heap(hep_Num+1,hep_Num+1+Len_Num);
}
int get_Num(){
pop_heap(hep_Num+1,hep_Num+1+Len_Num);
return -hep_Num[Len_Num--];
}
void put_L(xcw x){
hep_L[++Len_L]=x;
push_heap(hep_L+1,hep_L+1+Len_L);
}
xcw get_L(){
pop_heap(hep_L+1,hep_L+1+Len_L);
return hep_L[Len_L--];
}
int main(){
for(T=read();T;T--){
memset(hsh,0,sizeof(hsh));
while(Len_Num) get_Num();
while(Len_L) get_L();
n=read();m=read();
for(int i=1;i<=m;i++) a[(i<<1)-1]=(xcw){read(),i,1},a[i<<1]=(xcw){read()+1,i,0};
sort(a+1,a+1+(m<<=1));
for(int i=1;i<=n;i++) put_Num(i);
for(int i=1,j=1;i<=n;i++){
while(a[j].x==i&&j<=m){
if(a[j].f) hsh[a[j].id]=1,put_L((xcw){-a[j].x,a[j].id,0});
else hsh[a[j].id]=0;
j++;
}
if(Len_L==0) printf("1"),que[i]=1;
else{
xcw Now=get_L();int P=-Now.x;
while(!hsh[Now.id]&&Len_L) Now=get_L();
if(hsh[Now.id]){
put_L(Now);
for(int j=P;j<-Now.x;j++) put_Num(que[j]);
que[i]=get_Num();
}else{
for(int j=P;j<i;j++) put_Num(que[j]);
que[i]=1;
}
printf("%d",que[i]);
}
printf(i==n?"\n":" ");
}
}
return 0;
}