poj 2528 Mayor's posters(线段树+离散化)

题目链接:http://poj.org/problem?id=2528

(RE了不知道多少发,又接连WA了好几发..Debug了一下午...)

题意:

在墙上贴海报,每个人都可以贴一张海报,长度不限,海报之间可以相互覆盖,问最后能看到多少张海报(不一定是全部看见)。


这道题的数据范围很大,用线段树不可能把所有建立那么多节点,可以把区间当成点,离散化优化空间。

在区间离散化的时候不能用普通的离散方式,但是这道题数据比较水,即使是错误的离散方式也能够AC。

举例来说:

三个区间:[1,10] [1,4] [6,10]

普通的离散化得到的结果为x[1]=1,x[2]=4,x[3]=6,x[4]=10;

当进行染色时,[1,4],[1,2],[3,4]

这样的话最终[1,4]区间将会被完全覆盖,答案为2,实际答案应该为3.

解决的方式是if(x[i]-x[i-1]>1),那么在x[i]和x[i-1]之间添加一个点,这样就不会上述情况。

然后之后是线段树,注意数组的大小!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int INF=0x3f3f3f3f;
const int maxn=20010;
int T,n;
int l[maxn],r[maxn],color[maxn<<4];
int x[maxn<<2],hash[maxn];
int ans;

struct node{
	int l;
	int r;
	int color;
}node[maxn<<4];

void PushDown(int id);//从父节点向下更新
void build(int id,int l,int r);//建树
void Update(int id,int l,int r,int c);//区间更新,进行[l,r]区间染色
void Query(int id,int l,int r);//查询[l,r]区间内不同的颜色数
int binary_search(int low,int high,int a);//二分查找a所在位置

int main(){
#ifndef ONLINE_JUDGE
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
#endif
    scanf("%d",&T);
    while(T--){
    	scanf("%d",&n);
    	int p=0;
    	for(int i=0;i<n;i++){
    		scanf("%d%d",&l[i],&r[i]);
    		x[p++]=l[i],x[p++]=r[i];
    	}
    	sort(x,x+p);//离散化
    	int cnt=1;
    	for(int i=1;i<p;i++)
    		if(x[i]!=x[i-1])
    			x[cnt++]=x[i];
    	for(int i=cnt-1;i>=1;i--)
    		if(x[i]-x[i-1]>1)
    			x[cnt++]=x[i-1]+1;
    	sort(x,x+cnt);
    	build(1,0,cnt);
    	for(int i=0;i<n;i++){
    		int left=binary_search(0,cnt,l[i]);
    		int right=binary_search(0,cnt,r[i]);
    		Update(1,left,right,i);
    	}
    	ans=0;
    	memset(hash,0,sizeof(hash));
    	Query(1,0,cnt);
    	printf("%d\n",ans);
    }
    return 0;
}

void PushDown(int id){
	node[id<<1].color=node[id<<1|1].color=node[id].color;
	node[id].color=-1;
}

void build(int id,int l,int r){
	node[id].l=l;
	node[id].r=r;
	node[id].color=-1;
	if(l==r) return ;
	int mid=(l+r)>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
}

void Update(int id,int l,int r,int c){
	int L=node[id].l,R=node[id].r;
	if(l<=L&&R<=r){
		node[id].color=c;
		return ;
	}
	if(node[id].color!=-1) PushDown(id);
	int mid=(L+R)>>1;
	if(l<=mid)	Update(id<<1,l,r,c);
	if(r>mid)	Update(id<<1|1,l,r,c);
}

void Query(int id,int l,int r){
	if(node[id].color!=-1){
		if(!hash[node[id].color])
			ans++;
		hash[node[id].color]=1;
		return ;
	}
	if(l==r) return ;
	int mid=(l+r)>>1;
	Query(id<<1,l,mid);
	Query(id<<1|1,mid+1,r);
}

int binary_search(int low,int high,int a){
	while(low<=high){
		int mid=(low+high)>>1;
		if(x[mid]==a) return mid;
		else if(x[mid]>a) high=mid-1;
		else low=mid+1;
	}
	return -1;
}


你可能感兴趣的:(poj 2528 Mayor's posters(线段树+离散化))