ACM常用模板——数据结构——树状数组

(一)
一维BIT求和
模型:求区间[l,r]的和
   
   
  1. #define maxn 10005
  2. using namespace std;
  3. int n,bit[maxn];
  4. int sum(int i)//前i项的和
  5. {
  6. int s=0;
  7. while(i>0)s+=bit[i],i-=i&-i;
  8. return s;
  9. }
  10. void add(int i,int x)//第i项增加x,更新bit数组
  11. {
  12. while(i<=n){bit[i]+=x;i+=i&-i;}
  13. }
  14. int main()
  15. {
  16. int i,x,s,e,m;
  17. while(~scanf("%d%d",&n,&m)){
  18. memset(bit,0,sizeof(bit));
  19. for(i=1;i<=n;i++){
  20. scanf("%d",&x);
  21. add(i,x);
  22. }
  23. while(m--){
  24. scanf("%d%d",&s,&e);
  25. printf("%d\n",sum(e)-sum(s-1));
  26. }
  27. }
  28. }

(二)树状数组求逆序数
   
   
  1. #define maxn 10005
  2. using namespace std;
  3. int n,bit[maxn],a[maxn];
  4. int sum(int i)//前i项的和
  5. {
  6. int s=0;
  7. while(i>0)s+=bit[i],i-=i&-i;
  8. return s;
  9. }
  10. void add(int i,int x)//第i项增加x,更新bit数组
  11. {
  12. while(i<=n){bit[i]+=x;i+=i&-i;}
  13. }
  14. int solve()//求逆序数个数
  15. {
  16. int ans=0,i;
  17. for(i=0;i<n;i++){
  18. ans+=i-sum(a[i]);
  19. add(a[i],1);
  20. }
  21. return ans;
  22. }
  23. int main()
  24. {
  25. int i;
  26. while(~scanf("%d",&n)){
  27. memset(bit,0,sizeof(bit));
  28. for(i=0;i<n;i++){
  29. scanf("%d",&a[i]);
  30. }
  31. printf("%d\n",solve());
  32. }
  33. }
(三)二维树状数组
模型:矩阵初始化为0,C x1 y1 x2 y2:把矩阵翻转(0变1,,1变0),Q x y:查询位置x y的值
   
   
  1. const int MAXN = 1010;
  2. int c[MAXN][MAXN];
  3. int n;
  4. int sum(int x,int y)
  5. {
  6. int ret = 0;
  7. for(int i = x;i > 0;i -= i&(-i))
  8. for(int j = y;j > 0;j -= j&(-j))
  9. ret += c[i][j];
  10. return ret;
  11. }
  12. void add(int x,int y,int val)
  13. {
  14. for(int i = x;i <= n;i += i&(-i))
  15. for(int j = y;j <= n;j += j&(-j))
  16. c[i][j] += val;
  17. }
  18. int main()
  19. {
  20. int T;
  21. scanf("%d",&T);
  22. while(T--)
  23. {
  24. int q;
  25. scanf("%d%d",&n,&q);
  26. memset(c,0,sizeof(c));
  27. char op[10];
  28. int x1,y1,x2,y2;
  29. while(q--)
  30. {
  31. scanf("%s",op);
  32. if(op[0] == 'C')
  33. {
  34. scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
  35. add(x1,y1,1);
  36. add(x2+1,y1,1);
  37. add(x1,y2+1,1);
  38. add(x2+1,y2+1,1);
  39. }
  40. else
  41. {
  42. scanf("%d%d",&x1,&y1);
  43. if(sum(x1,y1)%2 == 0)printf("0\n");
  44. else printf("1\n");
  45. }
  46. }
  47. if(T > 0)printf("\n");
  48. }
  49. return 0;
  50. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值