大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

P3740 [HAOI2014]贴海报

线段树

\(O(nlogn)\)

本来是做过这道题的,原题是POJ2528 Mayor's posters

但是POJ上的数据有问题,导致我以为自己AC了。像这种区间的题尤其要注意离散化时要离散化左右边界

举个洛谷上的例子

当出现这种情况[5,7],[1,5],[7,8]按顺序覆盖的话,就会出问题:

离散化为区间[2,3],[1,2],[3,4]那么按这样覆盖就会把第一张海报覆盖掉,但实际上第一张海报没有完全被覆盖
那该怎么办?solution:在每个离散区间中强行加一个点比如说在[1,5]加上2,[5,7]加上6,[7,8]由于是相邻的所以不要加

这样问题就解决了

回顾这道题,因为是区间修改,所以可以用线段树。查询答案时既可以递归到叶子节点再返回,也可以遇到一个有颜色的区间便返回。在维护上传标记时,若左右儿子颜色相同才上传,否则不上传

这是修改后的代码

#include<bits/stdc++.h>
using namespace std;
#define go(i,a,b) for(int i=(a);i<=(b);++(i))
#define com(i,a,b) for(int i=(a);i>=(b);--(i))
#define mem(a,b) memset((a),(b),sizeof(a))
#define inf 0x3f3f3f3f
#define fin freopen("input.txt","r",stdin)
#define fout freopen("output.txt","w",stdout)
typedef long long ll;
const int maxn=10008;
struct tree{
	int l,r,co;
	#define l(x) t[x].l
	#define r(x) t[x].r
	#define co(x) t[x].co
	#define lson rt<<1
	#define rson rt<<1|1
}t[maxn*8];
int n,m,ans,sad[maxn*2],rk[maxn*2],tot=0,l[maxn],r[maxn],vis[maxn];
bool flag[maxn];

void read(int &x){
    int f=1;char s=getchar();x=0;
    while(!isdigit(s)){if(s=='-') f=-1;s=getchar();}
    while(isdigit(s)){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
    x*=f;
}

void build(int rt,int l,int r){
	l(rt)=l,r(rt)=r;
	if(l==r){
		return;
	}
	int mid=l+r>>1;
	build(lson,l,mid);
	build(rson,mid+1,r);
}

void push_up(int rt){
	if(co(lson)==co(rson)) co(rt)=co(lson);
	else co(rt)=-1;
}
void push_down(int rt){
	if(co(rt)!=-1&&co(rt)!=0){
		co(lson)=co(rt);
		co(rson)=co(rt);
		co(rt)=0;
	}
}

void update(int rt,int x,int y,int val){
	if(l(rt)>=x&&r(rt)<=y){
		co(rt)=val;
		return;
	}
	push_down(rt);
	int mid=l(rt)+r(rt)>>1;
	if(x<=mid) update(lson,x,y,val);
	if(y>mid) update(rson,x,y,val);
	push_up(rt);
}

void get_ans(int rt){
	if(co(rt)>0){
		flag[co(rt)]=1;
		return;
	}
	if(l(rt)==r(rt)) return;
	get_ans(lson),get_ans(rson);
}

int main(){
	//fin;
	int T;read(T);
	while(T--){
		mem(flag,0);
		read(m);
		ans=tot=0;
		mem(vis,0);
		go(i,1,m){
			read(l[i]),read(r[i]);
			sad[++tot]=l[i],rk[tot]=l[i];
			sad[++tot]=r[i],rk[tot]=r[i];
			sad[++tot]=l[i]+1,rk[tot]=l[i]+1;
			sad[++tot]=r[i]+1,rk[tot]=r[i]+1;
			sad[++tot]=l[i]-1,rk[tot]=l[i]-1;
			sad[++tot]=r[i]-1,rk[tot]=r[i]-1;
		}
		sort(sad+1,sad+tot+1);
		tot=unique(sad+1,sad+tot+1)-sad-1;
		go(i,1,m){
			l[i]=lower_bound(sad+1,sad+tot+1,l[i])-sad;
			r[i]=lower_bound(sad+1,sad+tot+1,r[i])-sad;
			int f=1;
		}
		build(1,1,tot);
		go(i,1,m){
			update(1,l[i],r[i],i);
		}
		get_ans(1);
		go(i,1,m) ans+=flag[i];
		printf("%d\n",ans);
	}
	return 0;
}

posted @ 2019-09-01 19:57  White_star  阅读(112)  评论(0编辑  收藏  举报
}