P3372 【模板】线段树 1
很好的题解链接,学到了懒标记和线段树的更容易写的版本。https://llkabs.blog.luogu.org/xian-duan-shu
本题主要解决区间修改,而不是单点修改。
ac代码如下
#include<bits/stdc++.h> using namespace std; typedef long long int ll; const int maxn=500005+5; struct node{ ll l,r,lazy,sum; }tree[4*maxn]; vector<ll>a(maxn); void build_tree(int node,int l,int r) { tree[node].l=l; tree[node].r=r; if(l==r){ tree[node].sum=a[l]; return ; } int mid=(l+r)>>1; int lnode=node*2+1; int rnode=node*2+2; build_tree(lnode,l,mid); build_tree(rnode,mid+1,r); tree[node].sum=tree[lnode].sum+tree[rnode].sum; } void down(int node) { tree[node*2+1].lazy+=tree[node].lazy; tree[node*2+1].sum+=(tree[node*2+1].r-tree[node*2+1].l+1)*tree[node].lazy; tree[node*2+2].lazy+=tree[node].lazy; tree[node*2+2].sum+=(tree[node*2+2].r-tree[node*2+2].l+1)*tree[node].lazy; tree[node].lazy=0; } void update(int node,int x,int y,int k) { if(tree[node].l>y||tree[node].r<x)return ; if(tree[node].l>=x&&tree[node].r<=y){ tree[node].lazy+=k; tree[node].sum+=(tree[node].r-tree[node].l+1)*k; return; } if(tree[node].lazy>0)down(node); update(node*2+1,x,y,k); update(node*2+2,x,y,k); tree[node].sum=tree[node*2+1].sum+tree[node*2+2].sum; } ll query(int node,int x,int y) { if(tree[node].l>y||tree[node].r<x)return 0; if(tree[node].l>=x&&tree[node].r<=y){ return tree[node].sum; } if(tree[node].lazy>0)down(node); return query(2*node+1,x,y)+query(2*node+2,x,y); } void show(){ for(int i=0;i<15;i++){ cout<<"**"<<tree[i].sum<<"**"<<endl; } } int main() { int n,m,op,x,y,k;scanf("%d%d",&n,&m); for(int i=0;i<n;i++)scanf("%ld",&a[i]); build_tree(0,0,n-1); for(int i=0;i<m;i++){ scanf("%d",&op); if(op==1){ scanf("%d%d%d",&x,&y,&k); update(0,x-1,y-1,k); /// show(); } else{ scanf("%d%d",&x,&y); cout<<query(0,x-1,y-1)<<endl; } } } /* 8 10 659 463 793 740 374 330 772 681 1 5 8 39 2 5 8 1 3 6 3 1 5 8 90 1 1 5 21 2 3 8 1 3 8 17 1 4 7 52 2 2 6 1 2 7 41 */