HDU Distinct Values

/*
一开始想到的是 对于每个区间操作
先按左端点排序(包含的区间 留这打的区间)
我们维护pos表示 a数组找到了哪
对于当前这个区间 只需要找 pos--r这个区间
用set维护能用的数 没放到a中一个 就在set里面删除
对于下次处理的区间 上次的l到这次的l里的数 再扔到set里面

然后 本地跑4+s 怎么搞都过不了......

其实可以不用对区间操作, 这样子常数比较大
直接维护每个点 向左延伸到哪(就是这个区间里的数不重复)
我们填i的时候 它向左延伸的左端点l 一定比i-1的l要大
所以拿个指针走一走 
常数小 
另外说一句 多校太可怕了.....
25号继续相约hdu
*/ #include<cstdio> #include<iostream> #include<set> #define maxn 100010 using namespace std; int T,n,m,pre[maxn],a[maxn]; set<int>s; int main(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); int pos=1,l,r;s.clear(); for(int i=1;i<=n;i++)a[i]=0; for(int i=1;i<=n;i++)pre[i]=i; for(int i=1;i<=n;i++)s.insert(i); for(int i=1;i<=m;i++){ scanf("%d%d",&l,&r); pre[r]=min(pre[r],l); } for(int i=n-1;i>=1;i--) pre[i]=min(pre[i],pre[i+1]); for(int i=1;i<=n;i++){ while(pos<pre[i]){ s.insert(a[pos]);pos++; } a[i]=*s.begin();s.erase(a[i]); } for(int i=1;i<n;i++) printf("%d ",a[i]==0?1:a[i]); printf("%d\n",a[n]==0?1:a[n]); } return 0; } tle #include<cstdio> #include<algorithm> #include<set> #include<cstdlib> #define maxn 100010 using namespace std; int T,n,N,m,a[maxn]; struct node{ int l,r; }A[maxn],B[maxn]; set<int> s; int cmp(const node &X,const node &Y){ if(X.l==Y.l)return X.r>Y.r; return X.l<Y.l; } int init(){ int x=0;char s=getchar(); while(s<'0'||s>'9')s=getchar(); while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x; } int main(){ T=init(); while(T--){ n=init();m=init(); s.clear();N=0; for(int i=1;i<=n;++i)a[i]=0; for(int i=1;i<=m;++i){ B[i].l=init();B[i].r=init(); } sort(B+1,B+1+m,cmp); for(int i=1;i<=m;++i) if(B[i+1].l>=B[i].l&&B[i+1].r<=B[i].r)continue; else A[++N]=B[i]; int pos=A[1].l-1,st;set<int>::iterator p; for(int i=1;i<=n;++i)s.insert(i); for(int i=1;i<=N;++i){ st=pos+1; for(p=s.begin();p!=s.end();++p){ a[++pos]=*p; if(pos>=A[i].r)break; } for(int j=st;j<=pos;++j) s.erase(a[j]); for(int j=A[i+1].l-1;j>=A[i].l;--j) s.insert(a[j]); } for(int i=1;i<=n;++i) printf("%d ",a[i]==0?1:a[i]); printf("\n"); } return 0; }

猜你喜欢

转载自www.cnblogs.com/yanlifneg/p/9357108.html
今日推荐