线段树——内存池
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 }