非递归线段树专题

Posted yijiull

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了非递归线段树专题相关的知识,希望对你有一定的参考价值。

学习了自底向上的非递归线段树,深感精妙!!

大牛的博客:http://blog.csdn.net/zearot/article/details/48299459

张坤玮---统计的力量

The Union of k-Segments

 CodeForces - 612D

题意:求被覆盖k次及以上的点或者线段。

看到别人直接用扫描线写的,更方便一些。

不过拿来练习线段树也不错。

技术分享
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1000010;
 4 int cn,c[maxn<<1];  //离散化
 5 int n,k,l[maxn],r[maxn];
 6 void discrete(){
 7     sort(c+1,c+1+cn);
 8     int I=1;
 9     for(int i=2;i<=cn;i++) if(c[i]!=c[i-1]) c[++I]=c[i];
10     cn=I;
11 }
12 int getid(int x){
13     int L=1,R=cn,m;
14     while(L<=R){
15         m=(L+R)>>1;
16         if(c[m]==x) return m;
17         if(c[m]<x) L=m+1;
18         else R=m-1;
19     }
20 }
21 int N;
22 int add[maxn<<3],p[maxn<<3];
23 void build(int n){
24     N=1;while(N<n+2) N<<=1;
25     memset(add,0,sizeof(add));
26     memset(p,0,sizeof(p));
27 }
28 void update(int L,int R){
29     for(int s=N+L-1,t=N+R;s^t^1;s>>=1,t>>=1){
30         if(~s&1) ++add[s^1];
31         if( t&1) ++add[t^1];
32     }
33     for(int s=N+L-1,t=N+R+1;s^t^1;s>>=1,t>>=1){
34         if(~s&1) ++p[s^1];
35         if( t&1) ++p[t^1];
36     }
37 }
38 void pushdown(){
39     for(int i=1;i<N;i++){
40         add[i<<1]+=add[i];
41         add[i<<1|1]+=add[i];
42         p[i<<1]+=p[i];
43         p[i<<1|1]+=p[i];
44     }
45 }
46 
47 int main(){
48     while(scanf("%d%d",&n,&k)!=EOF){
49         for(int i=cn=0;i<n;i++){
50             scanf("%d%d",&l[i],&r[i]);
51             c[++cn]=l[i];
52             c[++cn]=r[i];
53         }
54         discrete();
55         build(cn);
56         for(int i=0;i<n;i++){
57             update(getid(l[i]),getid(r[i]));
58         }
59         pushdown(); //下推!!
60         //统计
61         int flag=0,cnt=0;
62         for(int i=1;i<=cn;i++){
63             if(add[N+i]>=k){
64                 if(!flag){  //左端点
65                     l[++cnt]=c[i];
66                     flag=1;
67                 }
68             }else{
69                 if(flag){  //右端点
70                     r[cnt]=c[i];
71                     flag=0;
72                 }else {
73                     if(p[N+i]>=k){
74                         l[++cnt]=c[i];
75                         r[cnt]=c[i];
76                     }
77                 }
78             }
79         }
80         printf("%d\n",cnt);
81         for(int i=1;i<=cnt;i++){
82             printf("%d %d\n",l[i],r[i]);
83         }
84     }
85     return 0;
86 }
View Code

 

以上是关于非递归线段树专题的主要内容,如果未能解决你的问题,请参考以下文章

zkw线段树

非递归线段树

线段树的基础非递归的使用

二叉树专题

ZKW线段树

解析·优化 ZKW线段树