1. 程式人生 > 其它 >線段樹離散化 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; }