这道题如果直接建树/虽然可以建成,但一定会先炸内存
所以这题需要用到离散化
离散化,就是将一些数字给变小点,但是整体所具有的单调状况不变
离散化知道但是练习题目--没有去找,这道题还是去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;
}