藍書(演算法競賽進階指南)刷題記錄——POJ3468 A Simple Problem with Intergers(樹狀陣列維護差分)
阿新 • • 發佈:2018-11-10
題目:poj3468.
題目大意:給定一個序列a,要求支援:
1.格式C a b c,表示將[a,b]的權值都加上c.
2.格式Q a b,表示查詢[a,b]的權值和.
線段樹裸題(我像個傻子一樣寫了個LCT做了一遍),可是我們這裡不用線段樹,我們討論樹狀陣列的解法.
我們已經知道樹狀陣列支援單點修改區間查詢和區間修改單點查詢,那麼可不可以讓樹狀陣列支援區間修改區間查詢呢?
我們現在繼續將思路留在差分陣列上,我們設A是a的差分陣列,那麼A[1,n]的和就是.
我們發現這個東西用一個樹狀陣列還是不好維護,我們可以在變式.
我們發現這個東西貌似就可以用兩個樹狀陣列維護,我們可以用一個樹狀陣列維護A[i],再用一個樹狀陣列維護A[i]*(i-1).
程式碼如下:
//#include<bits/stdc++.h> #include<iostream> using namespace std; #define Abigail inline void typedef long long LL; const int N=100000; LL c[N+9][2],a[N+9]; int n,q; int lowbit(int x){return x&-x;} void add(int x,LL num,int t){ while (x<=n){ c[x][t]+=num; x+=lowbit(x); } } LL query(int x,int t){ LL sum=0; while (x){ sum+=c[x][t]; x-=lowbit(x); } return sum; } char rc(){ char c=getchar(); while (c<'A'||c>'Z') c=getchar(); return c; } Abigail into(){ scanf("%d%d",&n,&q); for (int i=1;i<=n;i++) scanf("%lld",&a[i]); } Abigail work(){ for (int i=n;i>=1;i--) a[i]-=a[i-1]; for (int i=1;i<=n;i++) add(i,a[i],0),add(i,a[i]*(i-1),1); } Abigail getans(){ char opt; int l,r; LL d; for (int i=1;i<=q;i++){ opt=rc(); if (opt=='C'){ scanf("%d%d%lld",&l,&r,&d); add(l,d,0);add(r+1,-d,0); add(l,d*(l-1),1);add(r+1,-d*r,1); }else{ scanf("%d%d",&l,&r); printf("%lld\n",query(r,0)*r-query(r,1)-query(l-1,0)*(l-1)+query(l-1,1)); } } } int main(){ into(); work(); getans(); return 0; }