【题解】畜栏预定

【题解】畜栏预定

嘿嘿又是普及题

至少要把线段分成多少个集合使得所有相交的线段不在一个集合输出方案。

显然我们让没一个线段覆盖的所有下标加上1,最后查询全局最大值就是答案,这样太显然了。直接树状数组(O(n log n)),或许有(O(n))算法,有没有人教一下我。

然后得到这个集合数目之后直接模拟一下,输出方案即可。

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>

using namespace std;  typedef long long ll;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(c<48||c>57)f|=c==45,c=getchar();
      while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}
const int maxn=50005;
const int maxm=1e6+1;
int seg[maxm];
int Lb;
#define lowbit(x) ((x)&(-x))
int n,m;


inline void add(const int&pos,const int&tag){
      for(register int t=pos;t<=Lb;t+=lowbit(t)) seg[t]+=tag;
}

inline int q(const int&pos){
      register int ret=0;
      for(register int t=pos;t;t-=lowbit(t)) ret+=seg[t];
      return ret;
}

vector < int > ve[maxm];
queue  < int > Q;
int arc[maxn];
int sav[maxn];
int cnt,len;


int main(){
      n=qr();
      for(register int t=1,t1,t2;t<=n;++t){
	    t1=qr();t2=qr();
	    ve[t1].push_back(t);
	    ve[t2+1].push_back(-t);
	    Lb=max(Lb,t2+2);
	    add(t1,1);add(t2+1,-1);
      }
      
      int ans=0;
      for(register int t=1;t<=Lb;++t)
	    ans=max(ans,q(t));
      for(register int t=1;t<=ans;++t) Q.push(t);
      for(register int t=1;t<=Lb;++t) {
	    for(register int i=0,ed=ve[t].size();i<ed;++i)
		  if(ve[t][i]<0)
			Q.push(arc[-ve[t][i]]);
	    for(register int i=0,ed=ve[t].size();i<ed;++i){
		  if(ve[t][i]<0)continue;
		  arc[ve[t][i]]=Q.front();
		  Q.pop();
	    }
      }
      arc[0]=ans;
      for(register int t=0;t<=n;++t) printf("%d
",arc[t]);
      return 0;
}

原文地址:https://www.cnblogs.com/winlere/p/11223732.html