其他分享
首页 > 其他分享> > 线段树离散化 zoj2528

线段树离散化 zoj2528

作者:互联网

离散化   当不需要那么多结点的时候,就需要将题目给的区间给离散化。

题目输入n个区间 ab。将a,b对应存入到数组ls中。( 第一个区间的ab分别是ls[0],ls[1]

将所有a,b再保存到同一个数组c里,对c数组进行排序(sort)和去重(unique(c,c+p)-c)得到有多少个不重复的点。

然后使用lower_boundc区间里找到每个区间的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; }

  

标签:node,线段,tree,mid,离散,add,zoj2528,lz,LL
来源: https://www.cnblogs.com/opanc/p/15541372.html