P3372 【模板】线段树 1
模板题呦,听老师说第一遍打板子很难??可是我第一遍打完之后就改了一个小地方就过了??emmmm可能是我太聪明了吧~~~
那不多bb,具体一点的解释在代码里
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | #include<bits/stdc++.h> using namespace std; const int N=1000005; #define ll long long int n,m; ll a[N],p[N]; void build( int k, int l, int r){ //建树 if (l==r){ //当到达根节点的时候再读入,不用保存原数组 int u; scanf( "%d" ,&u); a[k]=u; return ; } int mid=(l+r)/2; build(k*2,l,mid); build(k*2+1,mid+1,r); a[k]=a[k*2]+a[k*2+1]; //从下往上处理 } void add( int k, int l, int r, int lo, int ro, int q){ if (l>ro||r<lo){ //无交集的情况 return ; } if (l==r){ //到达根节点 a[k]+=q; return ; } if (l>=lo&&r<=ro){ //覆盖的情况直接返回值,并用懒惰标记 p[k]+=q; a[k]+=q*(r-l+1); return ; } //下面为有交集但无覆盖 int mid=(l+r)/2; if (p[k]){ //若有懒惰标记,则进行push_down操作 p[k*2]+=p[k]; p[k*2+1]+=p[k]; a[k*2]+=(mid-l+1)*p[k]; a[k*2+1]+=(r-mid)*p[k]; p[k]=0; } add(k*2,l,mid,lo,ro,q); //左右子树 add(k*2+1,mid+1,r,lo,ro,q); a[k]=a[k*2]+a[k*2+1]; //从下到上处理 } ll getsum( int k, int l, int r, int lo, int ro){ //求和 if (l>ro||r<lo){ //无交集 return 0; } if (l>=lo&&r<=ro){ //覆盖 return a[k]; } int mid=(l+r)/2; if (p[k]){ //push_down p[k*2]+=p[k]; p[k*2+1]+=p[k]; a[k*2]+=(mid-l+1)*p[k]; a[k*2+1]+=(r-mid)*p[k]; p[k]=0; } return getsum(k*2,l,mid,lo,ro)+getsum(k*2+1,mid+1,r,lo,ro); //返回和值 } int main(){ scanf( "%d%d" ,&n,&m); build(1,1,n); //建树 while (m--){ int l,r,t; scanf( "%d%d%d" ,&t,&l,&r); if (t==1){ int k; scanf( "%d" ,&k); add(1,1,n,l,r,k); //l-r增加k } else { printf( "%lld\n" ,getsum(1,1,n,l,r)); //求和 } //for(int i=1;i<=2*n;i++){//调试用 // printf("%d(%d) ",a[i],p[i]); //} //printf("\n"); } return 0; } |
白白
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步