A Simple Problem with Integers (線段樹區間更新區間求和)
阿新 • • 發佈:2019-02-12
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
InputThe first line contains two numbers N
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab. Output
You need to answer all Q
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4Sample Output
4 55 9 15Hint The sums may exceed the range of 32-bit integers.
程式碼:
query其他寫法#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int maxn = 100050; ll digit[maxn]; struct node { ll sum,lazy; int left,right; }tree[maxn*4]; //線段樹的建立 void build(int k,int l,int r) { tree[k].left = l; tree[k].right = r; tree[k].lazy = 0;//懶惰標記為 0 因為是區間更新所以容易超時這個時候就應該lazy標記 if(l==r) { tree[k].sum = digit[l]; return ; } int mid = (l+r)/2; build(k<<1,l,mid); build(k<<1|1,mid+1,r); tree[k].sum = tree[k<<1].sum + tree[k<<1|1].sum; } //釋放懶惰標記 void pushlazy(int k) { if(tree[k].lazy) { tree[k<<1].lazy += tree[k].lazy; tree[k<<1|1].lazy += tree[k].lazy; tree[k<<1].sum +=tree[k].lazy*(tree[k<<1].right-tree[k<<1].left+1); //這邊和下面那一行要注意的就是是!!tree[k].lazy* tree[k<<1|1].sum +=tree[k].lazy*(tree[k<<1|1].right-tree[k<<1|1].left+1); tree[k].lazy = 0; } } //線段樹的更新 void update(int k,int l,int r,ll val) { if(tree[k].left == l && tree[k].right == r) { tree[k].lazy +=val; //因為下面的其他節點都還沒有加上他們所應該的值所以不能為0 tree[k].sum += val * (r-l+1); //這一步是因為要加上這個的值 return ; } if(tree[k].left == tree[k].right) return; //因為是葉子節點所以說不用再向下釋放了直接可以return pushlazy(k);//釋放lazy標記 int mid = (tree[k].left + tree[k].right)>>1; if(r<=mid) update(k<<1,l,r,val); else if(l>mid) update(k<<1|1,l,r,val); else { update(k<<1,l,mid,val); update(k<<1|1,mid+1,r,val); } tree[k].sum = tree[k<<1].sum + tree[k<<1|1].sum;//這步要記得加 return; } ll query(int k,int l,int r) { if(tree[k].left == l && r == tree[k].right) { return tree[k].sum; } pushlazy(k); ll ans = 0; int mid = (tree[k].left + tree[k].right)>>1; if(r<=mid) ans+=query(k<<1,l,r); else if(l>mid) ans+=query(k<<1|1,l,r); else { ans+=query(k<<1,l,mid); ans+=query(k<<1|1,mid+1,r); } return ans; } int main() { int n,q,x,y;ll z; scanf("%d%d",&n,&q); for(int i = 1;i<=n;i++) scanf("%lld",&digit[i]); build(1,1,n); while(q--) { char s[5]; scanf("%s",s); if(s[0] == 'Q') { scanf("%d%d",&x,&y); printf("%lld\n",query(1,x,y)); }else { scanf("%d%d%lld",&x,&y,&z); update(1,x,y,z); } } return 0; }
ll query(int k,int l,int r)
{
if(tree[k].left >= l && tree[k].right <=r)
{
return tree[k].sum;
}
pushlazy(k);
ll ans = 0;
int mid = (tree[k].left + tree[k].right)>>1;
if(l<=mid)
ans+=query(k<<1,l,r);
if(r>mid)
ans+=query(k<<1|1,l,r);
return ans;
}