专题五 G-mayor‘s poster (离散化+线段树)

题意

对于一面长度为n的墙,有m块画板起点分别为a,b覆盖在墙上,问最后能看见多少个画板

思路

此题给定的n太大,直接进行线段树可能会爆空间时间 ,应进行离散化,但要注意离散化排序完若相邻两个数之间差为1,则无法正确区分出看到的画板,比如1 10,1 4,5 10 和1 10,1 4 ,6 10会被看成同一种情况,应在这种情况中间加入一个中间值

再进行线段树

代码

#include<iostream>
#include<algorithm> 
#include<cstring>
using namespace std;
const int N=1e4+5;
int M,L,R,ans;
int a[N],b[N];//记录m个板
int g[N*8],tr[N*16],vis[N];//g用来存储各个点的排序并进行离散化
//tr用来存各个值,vis数组用来存该板子是否被访问过

void pushdown(int x){
	if(tr[x]==-1)return;//该区间无板子;
	tr[x<<1]=tr[x<<1|1]=tr[x]; 
	tr[x]=-1;
} 

void update(int l,int r,int k,int x){
	if(L<=l&&r<=R){
		tr[x]=k;
		return;
	}
	pushdown(x);
	int mid=l+r>>1;
	if(L<=mid)update(l,mid,k,x<<1);
	if(R>mid)update(mid+1,r,k,x<<1|1);
     
}

void query(int l,int r,int x){
	if(tr[x]!=-1){
	 if(vis[tr[x]]==0)++ans;
	vis[tr[x]]=1;
	return ; 
    }
    if(l==r)return;
    int mid=l+r>>1;
    query(l,mid,x<<1);
    query(mid+1,r,x<<1|1);
}

int main(){
	int t;
	cin>>t;
	while(t--){
		cin>>M;
		int cnt=0;
		for(int i=1;i<=M;i++){
			cin>>a[i]>>b[i];
			g[cnt++]=a[i];
			g[cnt++]=b[i];
		} 
		sort(g,g+cnt);
		int m=unique(g,g+cnt)-g;//m代表去重后的所有元素数量
		int dnt=m;
		for(int i=0;i<=dnt-1;i++){
			if(g[i+1]-g[i]>1)g[m++]=g[i]+1;
		} 
		sort(g,g+m);//重新构造递增序列	
		memset(tr,-1,sizeof tr);
		memset(vis,0,sizeof vis);
		for(int i=1;i<=M;i++){
			L=lower_bound(g,g+m,a[i])-g;
			R=lower_bound(g,g+m,b[i])-g;
			update(0,m,i,1); 
		}	
		ans=0;
		query(0,m,1);
		cout<<ans<<endl;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值