加油!

计蒜客:区间整数操作-区间更新-区间和

给出N个整数A1,A2,..,Av,你需要处理区间加,区间求和。
输入格式
第一行两个整数N和Q(1≤N,Q≤105)。
第二行N个整数,表示A1,A2...Av(|A;≤109)的初始值。
接下来Q行,每行一个操作:
cabc,表示Aa,Aa+1…Ab每个数加c(lcl≤10000)。
Qab,表示询问Aa,Aa+1..Ab的和,答案可能超过32位整数。
输出格式
对于所有Q询问,一行输出一个答案。

代码:

复制
#include<bits/stdc++.h> using namespace std; typedef long long ll; /*区间更新,区间加值--区间求和*/ const int MAX_N = 1e5+5; ll s[4 * MAX_N],col[4 * MAX_N]; int n,q; //父节点合并 void up(int p){ s[p] = s[p * 2] + s[p * 2 + 1]; } //向下更新一层 区间更新使用延迟更新的思想提高效率 void down(int p, int l, int r){ if(col[p]){ int mid = (l + r) / 2; s[p * 2] += col[p] * (mid - l + 1); s[p * 2 + 1] += col[p] * (r - mid); col[p * 2] += col[p]; col[p * 2 + 1] += col[p]; col[p] = 0; } } //更新 void modify(int p,int l,int r,int x,int y,int c){ if(x <= l && r <=y){ s[p] += (r - l + 1) * c; //对父结点修改 如何是求区间最值而不是求和该如何修改呢? col[p] += c; //标记子节点需要延迟更新 return; } down(p, l, r);//向下更新一层 int mid = (l + r)/2; if(x <= mid){ modify(p * 2, l, mid, x, y, c); } if(y > mid){ modify(p * 2 + 1, mid + 1,r,x,y,c); } up(p); } //查询 ll query(int p,int l,int r,int x,int y){ if(x <= l && r <= y){ return s[p]; } down(p,l,r);//如果没有return,这时子节点必须更新了 就向下更新一层 int mid = (l + r) / 2; ll res = 0; if(x <= mid){ res += query(p * 2, l,mid,x,y); } if(y > mid){ res += query(p * 2 + 1,mid + 1,r,x,y); } return res; } int main(){ scanf("%d%d",&n,&q); for(int i=1;i<=n;i++){ ll d; scanf("%ld",&d); modify(1,1,n,i,i,d); } char ins; while(q--){ scanf(" %c",&ins); int a,b; ll c; if(ins=='Q'){ scanf("%d%d",&a,&b); printf("%lld\n",query(1,1,n,a,b)); }else{ scanf("%d%d%ld",&a,&b,&c); modify(1,1,n,a,b,c); } } return 0; }
posted @   fishers  阅读(370)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示