非递归线段树专题

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

大牛的博客: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

 

Glass Carving

 CodeForces - 527C

题意:分割矩形,求最大面积。

dalao题解http://blog.csdn.net/zearot/article/details/44759437

感觉有点无法驾驭。。。这个树有点反常。。。

好像是最后一层没有留首尾两个点,又因为0到n不可能被切(没有意义),所以只需保存1到n-1这些点,又把这些点左移一位,0到n-2。所以修改时也要左移一位。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=200010;
 4 int flag[maxn<<2][2];  //标价是否全是0
 5 int L[maxn<<2][2];  //左连续零
 6 int R[maxn<<2][2];  //右连续零
 7 int maxx[maxn<<2][2]; //最长连续零
 8 int M[2];
 9 
10 void pushup(int rt,int k){
11     flag[rt][k]=flag[rt<<1][k]&&flag[rt<<1|1][k];
12     maxx[rt][k]=max(max(maxx[rt<<1][k],maxx[rt<<1|1][k]),R[rt<<1][k]+L[rt<<1|1][k]);
13     L[rt][k]=flag[rt<<1][k]?L[rt<<1][k]+L[rt<<1|1][k]:L[rt<<1][k];
14     R[rt][k]=flag[rt<<1|1][k]?R[rt<<1|1][k]+R[rt<<1][k]:R[rt<<1|1][k];
15 }
16 void build(int n,int k){
17     M[k]=1;
18     while(M[k]<n) M[k]<<=1;
19     for(int i=0;i<M[k];i++) L[M[k]+i][k]=R[M[k]+i][k]=maxx[M[k]+i][k]=flag[M[k]+i][k]=i<n;
20     for(int i=M[k]-1;i>0;i--) pushup(i,k);
21 }
22 void update(int c,int k){
23     int s=M[k]+c-1;
24     flag[s][k]=maxx[s][k]=L[s][k]=R[s][k]=0;
25     for(s>>=1;s;s>>=1) pushup(s,k);
26 }
27 int main(){
28     int h,w,n;
29     while(scanf("%d%d%d",&w,&h,&n)!=EOF){
30         build(h-1,0);
31         build(w-1,1);
32         char s[5];int v;
33         for(int i=0;i<n;i++){
34             scanf("%s%d",s,&v);
35             s[0]=='H'?update(v,0):update(v,1);
36             printf("%lld\n",(long long)(maxx[1][0]+1)*(maxx[1][1]+1));
37         }
38     }
39 
40 }
线段树

 

A Simple Task

 CodeForces - 558E 

再补吧=_=||

posted @ 2017-08-05 00:44  yijiull  阅读(1243)  评论(0编辑  收藏  举报