poj 2528/ Mayor‘s posters/学习使用--离散化

这道题如果直接建树/虽然可以建成,但一定会先炸内存

所以这题需要用到离散化

 离散化,就是将一些数字给变小点,但是整体所具有的单调状况不变

 离散化知道但是练习题目--没有去找,这道题还是去c了一下离散化的处理过程

我用的一个很好想的lower_bound 离散方法

就是用两个数组存数据,一个作为离散数组,另一个是用来保存数据的数组

        sort(b+1,b+1+t);
		int xxx=unique(b+1,b+1+t)-b;
		for(int i=1;i<=t;i+=2)
			a[i]=lower_bound(b+1,b+1+xxx,a[i])-a;

 离散后就和正常的树状数组题目一样了

我还是用的  最简单,最好理解 的数组标记求答案

#include<iostream>
#include<algorithm>
#include<map>
#include<cstring>
using namespace std;
const int N=1e5+5;
int ans=0;
struct st
{
	int l,r,w;
}U[N*4];
int a[N],b[N],st[N];

void build(int u,int l,int r)
{
	U[u].l=l;U[u].r=r;
	U[u].w=0;
	if(l==r)	return;
	int mid=(l+r)/2;
	build(2*u,l,mid);
	build(2*u+1,mid+1,r);
}
void pushdown(int u)
{
	if(U[u].w==0)	return;
	U[2*u].w=U[u].w;
	U[2*u+1].w=U[u].w;
	U[u].w=0;
}
void update(int u,int l,int r,int w)
{
	if(l<=U[u].l&&U[u].r<=r)
	{
		U[u].w=w;
		return;
	}
//if (U[u].r<l||U[u].l>r)    return;//自己代码如果跑不出不妨加个特判
	pushdown(u);
	int mid=(U[u].l+U[u].r)/2; 
	if(l<=mid)	update(2*u,l,r,w);
	if(r>mid)	update(2*u+1,l,r,w);
}
void querry(int u)
{
	if(U[u].w>0)
	{
		if(st[U[u].w]==0)	ans++;
		st[U[u].w]=1;
		return;
	}
	if(U[u].l==U[u].r)	return;
	querry(2*u);
	querry(2*u+1);
}

int main()
{
	int T;cin>>T;
	while(T--)
	{
		int m;cin>>m;
		int t=0;
		build(1,1,100100);
		memset(st,0,sizeof st);
		for(int i=1;i<=m;i++)
		{
			int l,r;cin>>l>>r;
			t++;	a[t]=l,b[t]=l;
			t++;	a[t]=r+1,b[t]=r+1;
		}
		sort(b+1,b+1+t);
		int xxx=unique(b+1,b+1+t)-b;
		for(int i=1;i<=t;i+=2)
		{
			int lx=lower_bound(b+1,b+1+xxx,a[i])-b;
			int rx=lower_bound(b+1,b+1+xxx,a[i+1])-b;
			update(1,lx,rx-1,i);
		}
		ans=0;
		querry(1);
		cout<<ans<<'\n';
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值