模块装配
模块装配
(mdu.pas/c/cpp/in/out,1s,64MB)
题目描述
公元4774 年,宣称能够让人类一劳永逸地获取无限能源的“太阳开发计划”被正式提上了日程。政府首脑Ehrgeiz 慷慨激昂地对选民们说:“太阳的能量是永远也是用不完的!我们人类从此将进入一个再也不缺乏能源的时代!”在一片欢呼声中,突然一个声音传来:“可是,Ehrgeiz 先生,我们对于太阳能量的多寡以及人类对于能源的需求还没有了解到那个程度上,怎么能够做出这种断言呢?”提出异议的是科学院的领袖 Sonne。“Sonne 先生,事情不是明摆着的吗?太阳的能量足够使用至少50 亿年啊!显然是取之不尽的了!”“Ehrgeiz 先生,我必须提醒您,‘显然’是科学中最危险的一个词。”Sonne 正色说道,“我们在使用完地球的能源之后,现在又要糟蹋太阳了。我们在过去的一百年中用掉的能源比这之前整个文明史所使用的能源加在一起都要多。我很担心如果这个计划实施的话,不懂的节约的人类最终也会把太阳用光。”“哼,Sonne 先生,你就不要继续试图阻止这项计划了。你的理由根本就站不住脚。卫队,把Sonne 先生请出去吧。”Ehrgeiz 不屑一顾地说。“Ehrgeiz!你……”仪式结束之后,Ehrgeiz 叫来了项目主管Wolke。
“哼,又是那个 Sonne 给我难看。Wolke,准备工作做得怎么样了?”Wolke 说:“已经接近尾声了。但是还有一些特殊的模块没有装配完毕。”“那就赶紧去做啊!”Ehrgeiz 说。“可是,Ehrgeiz 先生,这些模块的安装非常复杂,而且需要一个最优的方案,否则我们的材料根本就不够。”Wolke 对Ehrgeiz 说。于是 Ehrgeiz 立刻想起了作为顶级信息学专家的你。你需要帮助Wolke 解决这个问题。“……喂喂,扯了半天淡,到底是什么问题啊!?”你着急地问。
具体来说是这样的:有 N 个模块需要安装在若干个连接器上。连接器和模块都可以看
作是一维的元件,连接器上有一排端口,模块要占用一段端口,一个端口只能给一个模块使用。由于模块的特殊性,第i 个模块需要占用连接器的[Ai, Bi]这一段端口。现在的问题是,如果所有的模块都需要被安装,至少需要多少个连接器,并给出一种可行方案。
输入格式
第一行是一个整数N,代表模块的数目。
之后 N 行,第i + 1 行有两个整数Ai, Bi。其中Ai 和Bi 表示第i 个模块需要占用的连接
器端口范围。
输出格式
第一行一个整数T,表示至少要使用多少个连接器。
之后 N 行,第i + 1 行包含一个整数Ki。Ki 是一个1 至T 之间的整数,表示第i 个模块
要占用的连接器编号。
样例输入
5
1 10
2 4
3 6
5 8
4 7
样例输出
4
1
2
3
2
4
样例中的情况自己yy
数据范围与约定
对于40% 的数据,N≤100。
对于 100% 的数据,N≤50000,1≤Ai, Bi≤106。
思路:搞一个小根堆,把所有模块的右端点全部加入,再让模块按照左端点由小到大排个序,之后再用个并查集维护各个模块之间的关系。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #include<cstring> 7 #include<string> 8 #include<queue> 9 using namespace std; 10 inline int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 17 int N; 18 struct node{ 19 int l,r; 20 int po; 21 int num; 22 }a[50005]; 23 int ans[50005]; 24 int fa[50005]; 25 inline int getfa(int x){ 26 if(fa[x]!=x) fa[x]=getfa(fa[x]); 27 return fa[x]; 28 } 29 30 int cmp(const node&w,const node&e){ 31 if(w.l<e.l) return 1; 32 return 0; 33 } 34 int cnt; 35 36 int heap[50005],heap_size; 37 int pos[50005];//记录堆中元素是第几个模块 38 int res,mini; 39 inline void put(int d,int h){ 40 int now,next; 41 heap[++heap_size]=d; 42 pos[heap_size]=h; 43 now=heap_size; 44 while(now>1){ 45 next=now>>1; 46 if(heap[next]<=heap[now]) return ; 47 swap(heap[next],heap[now]); 48 swap(pos[next],pos[now]); 49 now=next; 50 } 51 } 52 inline void get(){ 53 int now,next; 54 res=heap[1]; mini=pos[1]; 55 heap[1]=heap[heap_size]; 56 pos[1]=pos[heap_size--]; 57 now=1; 58 while(now<<1<=heap_size){ 59 next=now<<1; 60 if(next+1<=heap_size&&heap[next+1]<heap[next]) next++; 61 if(heap[now]<=heap[next]) return ; 62 swap(heap[now],heap[next]); 63 swap(pos[now],pos[next]); 64 now=next; 65 } 66 return ; 67 } 68 int main(){ 69 // freopen("mdu.in","r",stdin); 70 // freopen("mdu.out","w",stdout); 71 N=read(); 72 for(int i=1;i<=N;i++) a[i].l=read(),a[i].r=read(),a[i].po=i; 73 sort(a+1,a+N+1,cmp); 74 for(int i=1;i<+N;i++){ 75 put(a[i].r,i);//右端点全部加入堆,记录下标 76 fa[i]=i; 77 } 78 get(); 79 for(int i=1;i<=N;i++){ 80 if(res<a[i].l){ 81 int fai=getfa(i); 82 int famini=getfa(mini); 83 if(fai!=famini){ 84 if(fai<famini) fa[famini]=fai; 85 else fa[fai]=famini; 86 } 87 get(); 88 } 89 else continue; 90 } 91 92 for(int i=1;i<=N;i++){ 93 int fath=getfa(i); 94 if(fath!=i){//说明与其他模块公用连接器 95 if(a[fath].num!=0){ 96 a[i].num=a[fath].num; 97 } 98 else{ 99 cnt++; 100 a[fath].num=cnt; 101 a[i].num=cnt; 102 } 103 } 104 else{ 105 cnt++; 106 a[i].num=cnt; 107 } 108 } 109 110 for(int i=1;i<=N;i++){ 111 ans[a[i].po]=a[i].num; 112 } 113 cout<<cnt<<endl; 114 for(int i=1;i<=N;i++){ 115 cout<<ans[i]<<endl; 116 } 117 return 0; 118 }