线段树离散化 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; }
标签:node,线段,tree,mid,离散,add,zoj2528,lz,LL 来源: https://www.cnblogs.com/opanc/p/15541372.html