题目:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 64036 | Accepted: 18494 |
Description
- Every candidate can place exactly one poster on the wall.
- All posters are of the same height equal to the height of the wall; the width of a poster can be any integer number of bytes (byte is the unit of length in Bytetown).
- The wall is divided into segments and the width of each segment is one byte.
- Each poster must completely cover a contiguous number of wall segments.
They have built a wall 10000000 bytes long (such that there is enough place for all candidates). When the electoral campaign was restarted, the candidates were placing their posters on the wall and their posters differed widely in width. Moreover, the candidates started placing their posters on wall segments already occupied by other posters. Everyone in Bytetown was curious whose posters will be visible (entirely or in part) on the last day before elections.
Your task is to find the number of visible posters when all the posters are placed given the information about posters' size, their place and order of placement on the electoral wall.
Input
Output
The picture below illustrates the case of the sample input.
![](https://i-blog.csdnimg.cn/blog_migrate/85d8df2191db8df82ba259ebe2bfe93e.jpeg)
Sample Input
1 5 1 4 2 6 8 10 3 4 7 10
Sample Output
4
0,这个题归类于线段树的染色问题,我们把每一张海报当做在某一个区间上的染色,涉及到的就是线段树的成段更新。最后在询问一次,看有多少种“颜色”就好了
1,我们注意到,l,r的范围是很大的,相对而言n的值较小,我们于是考虑离散化。
所谓离散化,常规的是排序,去重合重新标号,比如 (3,100000 ) (100,1000) (1234,4321) 我们排序去重合用分别用0,1,2,3,4,5代替 3,100,1000,1234,4321,100000,然后我们要使用那几个区间时,可以用(0,5),(1,2),(3,4)代替。我们可以用map实现,当然也可以通过二分由值返回去找索引。
/*刚学的一招,因为这是一个单调的序列。
a[6]={3,100,1000,1234,4321,100000}。
*/
这个题由于它的特殊性,我们不能用这种普通离散化做。比如 (1,10), (1,4),(5,10) 和 (1,10) ,(1,4) (6,10) 用上面的方式是一样的。因为这个题每个数字表示的是一个单位长度。为了解决这种缺陷,我们可以在排序后的数组上加些处理,比如说[1,2,6,10]如果相邻数字间距大于1,我们就在中间插入一个数。那么就成了(1,2,3,6,7,10)再做线段树就行了。
code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int MAXN=3e4+5;
int col[MAXN<<4];
int left[MAXN],right[MAXN];
int x[MAXN*3],visit[MAXN];
int xx[MAXN*3];
int res,tot;
void PushDown(int rt){
if(col[rt]!=-1){
col[rt<<1]=col[rt<<1|1]=col[rt];
col[rt]=-1;
}
}
void Update(int L,int R,int modi,int l,int r,int rt){
if(l>=L&&r<=R){
col[rt]=modi;
return;
}
PushDown(rt);
int m=(l+r)>>1;
if(L<=m)Update(L,R,modi,lson);
if(R>m)Update(L,R,modi,rson);
}
void Query(int l,int r,int rt){
if(col[rt]!=-1){//说明这个rt所表示的区间被染色了
if(!visit[col[rt]]){
visit[col[rt]]=1;
++res;
}
return;
}
if(l==r)return;//说明这个点(区间)一直没有被染色。
int m=(l+r)>>1;
Query(lson);
Query(rson);
}
int bSearch(int num){
int lo=-1,hi=tot;
while(hi-lo>1){
int m=(hi+lo)>>1;
if(xx[m]>num)hi=m;
else if(xx[m]==num)return m;
else lo=m;
}
}
int main(){
int T;scanf("%d",&T);
while(T--){
int n;scanf("%d",&n);
for(int i=0;i<n;++i){
scanf("%d%d",&left[i],&right[i]);
x[i]=left[i];x[n+i]=right[i];
}
/*离散化*/
sort(x,x+2*n);
tot=0;
xx[tot++]=x[0];
for(int i=1;i<2*n;++i){
if(x[i]-x[i-1]==1)xx[tot++]=x[i];
else if(x[i]-x[i-1]>1){
xx[tot++]=x[i]-1;
xx[tot++]=x[i];
}
}
memset(visit,0,sizeof(visit));
memset(col,-1,sizeof(col));
for(int i=0;i<n;++i){
int L=bSearch(left[i]);//由值去找索引
int R=bSearch(right[i]);
Update(L,R,i,0,tot,1);//每一张海报就是一种颜色。
}
res=0;
Query(0,tot,1);
printf("%d\n",res);
}
return 0;
}