线段树 (区间覆盖模板)

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

以上是关于线段树 (区间覆盖模板)的主要内容,如果未能解决你的问题,请参考以下文章

AcWing 1264. 动态求连续区间和(线段树区间查询模板)

P3372 模板线段树 1(区间修改区间查询)(树状数组)

区间覆盖(线段树)

「模板」 线段树——区间乘 && 区间加 && 区间求和

模板线段树(区间加)

hdu1698(线段树区间替换模板)