本地搬运~
关于树状数组的学习,强烈推荐这个视频:https://www.bilibili.com/video/av26371798?from=search&seid=2141442207537065040
1:树状数组:查询和修改复杂度都为log(n)的数据结构,本身可用于单点修改区间查询,加入辅助数组后可实现区间修改:POJ3468
2:参考视频,我整理了这张图:
单点更新:
cin>>x; update(i,x); void update(int id,int x) { for(int i=id;i<=n;i+=lowbit(i)) c[i]+=x; }
查询[L,R]的区间和
cin>>i>>j; cout<<getsum(j)-getsum(i-1)<<endl; int getsum(int id) { int sum=0; for(int i=id;i>=1;i-=lowbit(i)) sum+=c[i]; return sum; }
lowbit求的是C[i]的i变为二进制后,从右往左找到第一个1的出现位置,固定这个1,其他全为0,再化为十进制。
int lowbit(int i) { return i&(-i); }
HDU1166:基本板子题:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=5e4+10; int c[maxn],n; int lowbit(int i) { return i&(-i); } void update(int id,int x) { for(int i=id;i<=n;i+=lowbit(i)) c[i]+=x; } int getsum(int id) { int sum=0; for(int i=id;i>=1;i-=lowbit(i)) sum+=c[i]; return sum; } int main() { int t; cin>>t; int ac=1; while(t--) { printf("Case %d: ",ac++); cin>>n; int x; memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { cin>>x; update(i,x); } string ch; while(cin>>ch) { if(ch=="End") { break; } if(ch=="Add") { int i,j; cin>>i>>j; update(i,j); } if(ch=="Sub") { int i,j; cin>>i>>j; update(i,-j); } if(ch=="Query") { int i,j; cin>>i>>j; cout<<getsum(j)-getsum(i-1)<<endl; } } } }