• 线段树——内存池


    #洛谷P2574

    new为C++中提供的一种“动态内存分配”机制,使得程序可以在运行期间,根据实际需求,要求操作系统临时分配一片内存空间用于存放数据;

    通过new运算符来实现;

    但是new的时间复杂度并不小,所以需要找一个方法来优化(或替代)new,来加快程序运行的速度

    (顺便A道黄题)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<math.h>
      5 #include<cstring>
      6 #define ll long long
      7 using namespace std;
      8 
      9 const ll maxn=2e5+10;
     10 ll n,m;
     11 ll a[maxn];
     12 char x[maxn];
     13 
     14 struct node
     15 {
     16     ll v;
     17     ll tag;
     18     ll l,r;
     19     node *ls,*rs;
     20     
     21     inline void pushup()
     22     {
     23         v=ls->v+rs->v;
     24     }
     25     
     26     inline void maketag()
     27     {
     28         v=(r-l+1)-v;//每进行一次修改,就是把0和1的数量交换,故用当前总数量减去当前1的数量,即为变换前0的数量,亦为变换后1的数量,每进行两次修改,就相当于没有进行修改操作
     29         tag^=1;//同一个数进行两次异或运算即为原数,故用tag作为是否进行异或的标记
     30     }
     31     
     32     inline void pushdown()//懒标记下传
     33     {
     34         if(!tag) return ;
     35         ls->maketag();
     36         rs->maketag();
     37         tag=0;
     38     }
     39     
     40     inline bool inrange(const ll L,const ll R)
     41     {
     42         return (L<=l)&&(r<=R);
     43     }
     44     inline bool outrange(const ll L,const ll R)
     45     {
     46         return (l>R)||(r<L);
     47     }
     48     
     49     inline void upd(const ll L,const ll R)//区间修改
     50     {
     51         if(inrange(L,R))
     52         {
     53             maketag();
     54         }
     55         else if(!outrange(L,R))
     56         {
     57             pushdown();
     58             ls->upd(L,R);
     59             rs->upd(L,R);
     60             pushup();
     61         }
     62     }
     63     inline ll qry(const ll L,const ll R)//区间查询
     64     {
     65         if(inrange(L,R)) return v;
     66         else if(outrange(L,R)) return 0;
     67         else
     68         {
     69             pushdown();
     70             return ls->qry(L,R)+rs->qry(L,R);
     71         }
     72     }
     73 } mem[(maxn<<1)+10];//线段树中最多一共有2n-1个节点,故将内存池空间扩大2倍
     74 
     75 node *pool=mem;//pool为一个静态内存池,指向Mem,当需要建立新的节点时,则让指针取得pool中的地址,借以替代new
     76 node *New(const ll L,const ll R)
     77 {
     78     node *u=pool++;
     79     
     80     u->l=L;
     81     u->r=R;
     82     u->tag=0;
     83     
     84     if(L==R)//该节点为叶子结点
     85     {
     86         u->ls=u->rs=NULL;
     87         u->v=a[L];
     88     }
     89     else//递归建树
     90     {
     91         ll M=(L+R)>>1;
     92         u->ls=New(L,M);
     93         u->rs=New(M+1,R);
     94         u->pushup();
     95     }
     96     return u;
     97 }
     98 
     99 
    100 int main(void)
    101 {
    102     scanf("%lld%lld",&n,&m);
    103     scanf("%s",x);
    104     for(int i=1;i<=n;i++)
    105     {
    106         a[i]=x[i-1]-'0';
    107     }
    108     node *rot=New(1,n);
    109     for(ll op,l,r;m;m--)
    110     {
    111         scanf("%lld%lld%lld",&op,&l,&r);
    112         if(op==0)
    113         {
    114             rot->upd(l,r);//修改
    115         }
    116         else
    117         {
    118             printf("%lld
    ",rot->qry(l,r));//查询
    119         }
    120     }
    121     return 0;
    122 }
  • 相关阅读:
    大话设计模式C++实现-第1章-简单工厂模式
    mac下的git的安装与简单的配置
    Execute failed: java.io.IOException: Cannot run program &quot;sdk-linux/build-tools/22.0.0/aapt&quot;: error=2
    UIScrollView 循环滚动,代码超简单
    字符编码的前世今生
    Android 4.4 KitKat 支持 u 盘功能
    Java Tread多线程(1)实现Runnable接口
    (hdu step 6.3.3)Air Raid(最小路径覆盖:求用最少边把全部的顶点都覆盖)
    每日算法之二十三:Reverse Nodes in k-Group
    Android4.0-4.4 加入实体按键振动支持的方法(java + smali版本号)
  • 原文地址:https://www.cnblogs.com/jd1412/p/13246053.html
Copyright © 2020-2023  润新知