其實這題應該是線段樹區間更新的模板題,我現在用樹狀陣列的方法做
理解樹狀陣列一維的區間更新和區間查詢需要一些基礎(知道的直接繼續往下看):
樹狀陣列 一維 單點更新 區間查詢(最基礎):
樹狀陣列 一維 區間更新 單點查詢:
其實樹狀陣列本質就是單點更新、區間查詢,其它用法都是通過轉化成本質用法實現
一維的區間更新和單點查詢是通過維護乙個差分陣列轉化實現,而一維的區間更新和區間查詢是通過維護乙個差分陣列和乙個與差分陣列有關的陣列轉化實現。
設原陣列是a[n],差分陣列c[n],c[i]=a[i]-a[i-1],那麼明顯地a[n]=∑n
i=1c
[i] ,如果想要修改a[i]到a[j] (比如+v),只需令c[i]+=v,c[j+1]-=v即可,到這區間更新就實現了。
那麼怎麼實現區間查詢呢?(比如查詢a[1]-a[n])
a[1] + a[2] + … + a[n]
= c[1] + (c[1]+c[2]) + … + (c[1]+c[2]+…+c[n])
= n*c[1] + (n-1)*c[2] + … + c[n]
= (n+1)*(c[1]+…+c[n]) - (1*c[1] + 2*c[2] + … + n*c[n])
所以我們在維護差分陣列c的同時維護與之相關的陣列c2[n] = n*c[n]即可
以poj3468為例,再看看**注釋應該就懂了。
//#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
ll a[maxn],c1[maxn],c2[maxn],n,q;
ll lowbit(ll x)
void update(ll x,ll value)
}ll query(ll x)
return (i+1)*tmp1-tmp2;
//tmp1 = c1[1]+...+c1[n],tmp2 = c2[1]+...+c2[n] = 1*c1[1]+...+n*c1[n]
//返回a[1]+...+a[x]
}int main()
int a,b;
char op;
while(q--)
else
}return
0;}
poj 3468 樹狀陣列 區間修改 區間求和
這是利用樹狀陣列進行 區間求和區間修改,寫起來比線段樹輕鬆許多,具體的原理參考大佬部落格 如下 1 2 poj 3468 樹狀陣列 區間修改 和 區間查詢 3原理 4c1 和 c2 是兩個差分陣列,所以輸入資料時 c1 i a i a i 1 56 7 include 8 include 9 inc...
POJ 3468(樹狀陣列的威力)
之前說過這是線段樹的裸題,但是當看了 這篇題解後我簡直震驚了,竟然能如此巧妙地轉化為用樹狀陣列來處理,附上部分截圖 最好還是進入原 細細品味 依照他的思路附上我的 1 include2 include3 define lowbit x x x 4 typedef long long ll 5 con...
poj3468 樹狀陣列的區間快速更新和查詢
直接用樹狀陣列會超時 所以必須快速更新。分析 由於本題更新的時候是區間更新 所以不能直接去乙個個更新區間內的點,肯定會超時 對於每次更新c a,b,d 表示區間 a,b 內的值增加d 用ans a 表示a n區間元素增加的值,所以對於c a,b,d 有 ans a d,ans b 1 d 則每次詢問...