线段树——内存池

#洛谷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\n",rot->qry(l,r));//查询
119         }
120     }
121     return 0;
122 }

 

posted @ 2020-07-05 14:53  雾隐  阅读(203)  评论(0编辑  收藏  举报