标签:
题目大意:在一块儿宣传栏中贴宣传单,规定宽度相同,长度不同。按一定顺序贴,给出宣传单的起始和结束位置,这里位置不能忽略成点(而是一段长度),问最后会看到几个宣传单。
解题思路:由于给出的数据范围多大,所以要先进行离散化减少复杂度,因为这里给出的不是”点“是带长度的,所以一般的离散化会出现离散失真,这里可以在离散的时候增加技巧,即在不相邻的数据里增加分隔点,凸显不连续。然后进行线段树成段替换,最后求出整个区间的不同宣传单个数。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define mid (L+R)/2
#define lson rt*2,L,mid
#define rson rt*2+1,mid+1,R
const int maxn=50000;
int lm[maxn/2],rm[maxn/2];
int col[maxn*4];
int Hash[maxn];
int A[maxn];
int num=0;
int discretization(int l,int r,int key){ //离散化
while(l<=r){
int m=(l+r)/2;
if(key==A[m]){
return m;
}else if(key<A[m]){
r=m-1;
}else{
l=m+1;
}
}
}
void PushDown(int rt){
if(col[rt]!=-1){
col[rt*2]=col[rt];
col[rt*2+1]=col[rt];
col[rt]=-1;
}
}
void update(int rt,int L,int R,int l_ran,int r_ran,int _col){
if(l_ran<=L&&R<=r_ran){
col[rt]=_col;
return ;
}
PushDown(rt);
if(l_ran<=mid)
update(lson,l_ran,r_ran,_col);
if(r_ran>mid)
update(rson,l_ran,r_ran,_col);
}
void query(int rt,int L,int R){
if(col[rt]!=-1){
if(!Hash[col[rt]]){
num++;
Hash[col[rt]]=1;
}
return ;
}
if(L==R)
return ;
query(lson);
query(rson);
}
void debug(){
for(int i=1;i<32;i++){
printf("%d %d\n",i,col[i]);
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,nn=0,m;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&lm[i],&rm[i]);
A[nn++]=lm[i];
A[nn++]=rm[i];
}
sort(A,A+nn);
m=1;
for(int i=0;i<nn-1;i++){ //去重
if(A[i]!=A[i+1]){
A[m++]=A[i+1];
}
}
for(int i=m-1;i>0;i--){ //添加分隔点
if(A[i]!=A[i-1]+1){
A[m++]=A[i-1]+1;
}
}
sort(A,A+m);
int tml,tmr;
memset(col,-1,sizeof(col));
for(int i=0;i<n;i++){
tml= discretization(0,m-1,lm[i]); //离散化
tmr= discretization(0,m-1,rm[i]); //离散化
update(1,0,m-1,tml,tmr,i);
}
// debug();
memset(Hash,0,sizeof(Hash));
num=0;
query(1,0,m-1);
printf("%d\n",num);
}
return 0;
}
POJ 2528——Mayor's posters——————【线段树区间替换、找存在的不同区间】
标签:
原文地址:http://www.cnblogs.com/chengsheng/p/4393566.html