线段树 (区间覆盖模板)
Posted C-DmLy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树 (区间覆盖模板)相关的知识,希望对你有一定的参考价值。
线段树
线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。
题目链接: http://acm.zzuli.edu.cn/zzuliacm/problem.php?id=1877
代码:
1 #include <cstdio> 2 #include <cmath> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 #include <queue> 7 #include <stack> 8 #include <map> 9 #include <set> 10 #include <vector> 11 #include <iostream> 12 using namespace std; 13 #define for0(i, n) for(int i=0; i<(n); ++i) 14 #define for1(i,a,n) for(int i=(a);i<=(n);++i) 15 #define for2(i,a,n) for(int i=(a);i<(n);++i) 16 #define for3(i,a,n) for(int i=(a);i>=(n);--i) 17 #define for4(i,a,n) for(int i=(a);i>(n);--i) 18 #define CC(i,a) memset(i,a,sizeof(i)) 19 #define LL long long 20 #define MOD 1000000007 21 #define inf 0x3f3f3f3f 22 23 #define EPS 1e-6 24 #define N 100010 25 #define lson p<<1 26 #define rson p<<1|1 27 28 struct num 29 { 30 int l,r; 31 }a[N]; 32 int v[N]; 33 34 struct node 35 { 36 int l,r,x; 37 int mid(){ 38 return (l+r)/2; 39 } 40 int len(){ 41 return (r-l+1); 42 } 43 }tree[N<<2]; 44 45 void buildtree(int p,int L,int R) 46 { 47 tree[p].l=L; 48 tree[p].r=R; 49 tree[p].x=0; 50 if(L==R) 51 return ; 52 53 buildtree(lson,L,tree[p].mid()); 54 buildtree(rson,tree[p].mid()+1,R); 55 } 56 57 void update(int p,int L,int R) 58 { 59 if(tree[p].l==L && tree[p].r==R){ 60 tree[p].x++; 61 return ; 62 } 63 if(R <= tree[p].mid()) 64 update(lson,L,R); 65 else if(L > tree[p].mid()) 66 update(rson,L,R); 67 else{ 68 update(lson,L,tree[p].mid()); 69 update(rson,tree[p].mid()+1,R); 70 } 71 } 72 73 void up(int p,int L,int R) 74 { 75 if(L==R) 76 return ; 77 tree[lson].x += tree[p].x; 78 tree[rson].x += tree[p].x; 79 80 up(lson,L,tree[p].mid()); 81 up(rson,tree[p].mid()+1,R); 82 83 tree[p].x = min(tree[lson].x,tree[rson].x); 84 } 85 86 int query(int p,int L,int R) 87 { 88 if(tree[p].l==L && tree[p].r==R) 89 return tree[p].x; 90 if(R <= tree[p].mid()) 91 return query(lson,L,R); 92 else if(L > tree[p].mid()) 93 return query(rson,L,R); 94 else 95 return min(query(lson,L,tree[p].mid()),query(rson,tree[p].mid()+1,R)); 96 97 } 98 99 int main() 100 { 101 int t; 102 scanf("%d",&t); 103 while(t--){ 104 int n,m,k=0,ans; 105 scanf("%d%d",&n,&m); 106 memset(a,0,sizeof(a)); 107 memset(v,0,sizeof(v)); 108 buildtree(1,1,n); 109 110 for(int i=1; i<=m; i++){ 111 scanf("%d%d",&a[i].l,&a[i].r); 112 update(1,a[i].l,a[i].r); 113 } 114 115 up(1,1,n); 116 117 for(int i=1; i<=m; i++){ 118 ans=query(1,a[i].l,a[i].r); 119 if(ans >= 2) 120 v[k++] = i; 121 } 122 printf("%d\n", k); 123 for(int i=0; i<k; i++) 124 printf("%d%c", v[i], i==k-1?‘\n‘:‘ ‘); 125 } 126 return 0; 127 }
另外的版本: https://hrbust-acm-team.gitbooks.io/acm-book/content/data_structure/ds_part3.html
以上是关于线段树 (区间覆盖模板)的主要内容,如果未能解决你的问题,请参考以下文章