線段樹離散化 zoj2528
阿新 • • 發佈:2021-11-11
離散化 當不需要那麼多結點的時候,就需要將題目給的區間給離散化。
題目輸入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;
}