线段树离散化 zoj2528
离散化 当不需要那么多结点的时候,就需要将题目给的区间给离散化。
题目输入n个区间 a,b。将a,b对应存入到数组ls中。( 第一个区间的ab分别是ls[0],ls[1] )
将所有a,b再保存到同一个数组c里,对c数组进行排序(sort)和去重(unique(c,c+p)-c)得到有多少个不重复的点。
然后使用lower_bound在c区间里找到每个区间的a b的索引,离散化完成。
#include<bits/stdc++.h>
#define ms(a,b) memset(a,b,sizeof(a))
#define fast ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define LL long long
#define ull unsigned long long
using namespace std;
const LL N=100100;
const LL maxx = 0x3f3f3f;
const LL mod = 1e9+7;
const LL minn = -0x3f3f3f;
const LL maxn = 400005;
using namespace std;
LL tree[4*N+1]; // 线段树
LL lz[4*N+1]; // 延迟标记
LL n,t;
set< LL > ans; (将所有颜色用set装起来,利用set自动去重的性质,最后set的数有几个,就是有多少海报)
// 创建线段树
void build(LL node,LL l,LL r){
if(l == r){
tree[node]=0;
return;
}
LL mid = (l+r)/2;
build(node*2,l,mid);
build(node*2+1,mid+1,r);
tree[node] = 0 ;
}
void push_down(LL node,LL l,LL r){
if(lz[node]){
LL mid = (l+r) / 2;
lz[node*2] = lz[node];
lz[node*2 + 1] = lz[node];
tree[node*2] = lz[node];
tree[node*2 + 1] = lz[node];
lz[node] = 0;
}
}
// 区间更新,lr为更新范围,LR为线段树范围,add为更新值
void update_range(LL node,LL l,LL r,LL L,LL R,LL add){
push_down(node,L,R);
if(l <= L && r >= R){
lz[node] = add;
tree[node] = add; // 更新方式
return;
}
LL mid = (L+R) / 2;
if(mid >= l) update_range(node*2,l,r,L,mid,add);
if(mid < r) update_range(node*2 + 1,l,r,mid+1,R,add);
if ( tree[node*2]==tree[node*2+1] ){
tree[node]=tree[node*2];
}else{
tree[node]=0;
}
}
// 区间查找
void query_range(LL node, LL L, LL R){
if ( tree[node]!=0 ){
ans.insert(tree[node]);
// cout<<node<<' '<<tree[node]<<endl;
return ;
}
if(L==R){
return ;
}
LL mid = (L+R) / 2;
query_range(node*2,L,mid);
query_range(node*2 + 1,mid+1,R);
return;
}
LL c[N]={},ls[N]={}; //c 用来离散化 ls用来映射
void solve()
{
LL a,b,k,p=0,i;
cin>>n;
build(1,1,20005);
while (n--){
cin>>a>>b;
ls[p]=a;c[p++]=a;
ls[p]=b;c[p++]=b;
}
// cout<<"p:"<<' '<<p<<endl;
sort(c,c+p); 对c数组进行排序
// for (i=0;i<p;i++) cout<<"c["<<i<<"]:"<<' '<<c[i]<<' ';
// cout<<endl;
int cnt=unique(c,c+p)-c; cnt为c数组中不重复的数的数量
// for (i=0;i<p;i++) cout<<"c["<<i<<"]:"<<' '<<c[i]<<' ';
// cout<<endl;
// cout<<"cnt"<<' '<<cnt<<endl;
for (i=0;i<p;i++) ls[i]=lower_bound(c,c+cnt,ls[i])-c+1;
找到大于等于自身的数的下标,索引到这个下标
// for (i=0;i<p;i++){
// cout<<ls[i]<<' ';
// if (i%2==1) cout<<endl;
// }
for (i=1;i<p;i+=2){
update_range(1,ls[i-1],ls[i],1,20005,i);
}
query_range(1,1,20005);
cout<<ans.size()<<endl;
// printf("%d\n",ansans);
}
int main()
{
fast;
cin>>t;
while ( t-- ){
ans.clear();
ms(ls,0);
ms(c,0);
ms(lz,0);
solve();
}
return 0;
}

浙公网安备 33010602011771号