zoukankan      html  css  js  c++  java
  • 非递归线段树专题

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

    大牛的博客: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
    ",cnt);
    81         for(int i=1;i<=cnt;i++){
    82             printf("%d %d
    ",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
    ",(long long)(maxx[1][0]+1)*(maxx[1][1]+1));
    37         }
    38     }
    39 
    40 }
    线段树

    A Simple Task

     CodeForces - 558E 

    再补吧=_=||

  • 相关阅读:
    mysql连接的空闲时间超过8小时后 MySQL自动断开该连接解决方案
    WebAPI 用户认证防篡改实现HMAC(二)签名验证 AbsBaseAuthenticationAttribute--转
    Calling a Web API From a .NET Client (C#)
    http状态码有那些?分别代表是什么意思
    html 之表单,div标签等。。。。。。。
    mysql之视图,触发器,事务等。。。
    pymysql模块
    MySQL之IDE工具介绍及数据备份
    mysql老是停止运行该怎么解决
    前端基础之html
  • 原文地址:https://www.cnblogs.com/yijiull/p/7288446.html
Copyright © 2011-2022 走看看