题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=116

士兵杀敌(一) 数组是固定的,所以可以用一个sum数组来保存每个元素的和就行,但是不能每次都加,因为那样会超时,查询次数太多。但是这个士兵杀敌(二)就不能用那个方法来解了,因为这个是动态的,中间元素的值可能会变化,所以引出一个新的东西来。刚开始想了一下,实在是没有想到方法,就去讨论区看了看,一看好像都说用树状数组,就去找树状数组的用法。

先上图,看着图解释容易理解点。

数组A是原数组中的元素,数组C是树状数组中的元素,图中C数组的元素组成为A中的某些元素之和,这些元素的个数取决于它的下标能被多少个2整除,像C[1] = A[1]; C[2] = A[1] + A[2]; C[3] = A[3]; C[4] = A[1] + A[2] + A[3] + [4] = C[2] + C[3]; ……这些个数可以写一个通式C[i] = A[n - 2^k + 1] + ……+A[i]; 其中k为 i 的二进制中从右往左数的 0 的个数 ,就像6有一个, 6可以写成 2 × 3, 所以C[6] = A[5] + A[6]; 所以可以定义一个函数来求这个数.

6的二进制为0110

5的二进制为0101

6^5 = 0011

6&(6^5) = 0010 = 十进制中的2

所以函数可以这么写

int lowbit(int N)//求n中有多少个能被2的多少次幂整除的,即2^k, 也就是树状数组的作用域
{return N & (N ^ (N - 1));
}

也可以写成

int lowbit(int N)//求n中有多少个能被2的多少次幂整除的,即2^k, 也就是树状数组的作用域
{return N & (-N);
}

更改一个数的值, 就要更改次数在树状数组中的所有祖先,不过这个时间复杂度是O(logn); 下面是更改值(添加杀敌数)的函数

void add(int pos, int num)//添加新值到树状数组中
{while(pos <= n){tmp[pos] += num;pos += lowbit(pos);}
}

下面就是求和函数, 因为这种方法之所以快,是求他的最小树根节点的和, 最小树的个数为当前要求的n的二进制中为1的个数,即展开式中能写成不同2的幂指数的项数,

例如: 15 = 2^3 + 2^2 + 2^1 + 2^0; 所以n = 15时, 最小数有四个,求和的时间复杂度为O(logn);

int Sum(int N)//求前N个数的和
{int sum = 0;while(N > 0){sum += tmp[N];N -= lowbit(N);}return sum;
}

关键就是这三步, 这三步搞明白了,基本上就不成问题了,但是,当时按照 杀敌(一) 中的思维,还统计了一个总数,那样不会快,反而会慢,所以直接求就行,下面是完整的代码

 1 #include <stdio.h>
 2 #include <string.h>
 3
 4 int tmp[1001000];
 5 int n, k;
 6
 7 int lowbit(int N)//求n中有多少个能被2的多少次幂整除的,即2^k, 也就是树状数组的作用域
 8 {
 9     return N & (-N);
10 }
11
12 void add(int pos, int num)//添加新值到树状数组中
13 {
14     while(pos <= n)
15     {
16         tmp[pos] += num;
17         pos += lowbit(pos);
18     }
19 }
20
21 int Sum(int N)//求前N个数的和
22 {
23     int sum = 0;
24     while(N > 0)
25     {
26         sum += tmp[N];
27         N -= lowbit(N);
28     }
29     return sum;
30 }
31
32 int main()
33 {
34     int a, b, temp;
35     char str[10];
36     scanf("%d %d", &n, &k);
37     for(int i = 1; i <= n; i++)
38     {
39         scanf("%d", &temp);
40         add(i, temp);
41     }
42     for(int i = 0; i < k; i++)
43     {
44         scanf("%s %d %d", str, &a, &b);
45         if(strcmp(str, "QUERY") == 0)
46             printf("%d\n", Sum(b) - Sum(a - 1));
47         else
48             add(a, b);
49     }
50
51     return 0;
52 }

转载于:https://www.cnblogs.com/Howe-Young/p/4009223.html

NYOJ 116士兵杀敌(二) 树状数组相关推荐

  1. NYOJ 116 士兵杀敌(二)

    士兵杀敌(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的军师,南将军经常想知 ...

  2. 【数据结构】树状数组 例题剖析

    目录 一.模板题 二.树状数组求逆序对 一.离散化 二.逆序对 三.待解决 P1428 小鱼比可爱 算法详解 一.模板题 模板题 题目描述 如题,已知一个数列,你需要进行下面两种操作: 将某一个数加上 ...

  3. nyoj116 士兵杀敌(二)树状数组 插点问线

    士兵杀敌(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的军师,南将军经常想知 ...

  4. 士兵杀敌(二)(线段树+树状数组)

    士兵杀敌(二) 时间限制:1000 ms  |           内存限制:65535 KB 难度:5 描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的军 ...

  5. NYOJ【士兵杀敌(二)】

    士兵杀敌(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的军师,南将军经常想知 ...

  6. 【二维树状数组】See you~

    https://www.bnuoj.com/v3/contest_show.php?cid=9148#problem/F [题意] 给定一个矩阵,每个格子的初始值为1.现在可以对矩阵有四种操作: A ...

  7. [LA7139 Rotation(2014 shanghai onsite)]二维树状数组

    题意:有一个n*m的矩形,一辆车从左上角出发,沿一条路径走,路径是由矩形上每个单元格的边构成的,最后回到左上角,求车子在每个格子转过圈数的平方和. 思路:假设需要记录每个格子转的顺时针的圈数(为负表示 ...

  8. HDU2642(二维的树状数组)

    二维的树状数组,我记得是模版!^ _ ^ 题意很清楚:就是这部分的原理:sum(x1,y1)+sum(x2-1,y2-1)-sum(x1,y2-1)-sum(x2-1,y1);其实可以和概率论中的一个 ...

  9. 点分治 + 树状数组 ---- E. Close Vertices(点分治 + 二维数点)

    题目链接 题目大意: 给出一棵树,问有多少条路径权值和不大于www,长度不大于lll 解题思路: 首先树上路径问题大概率就是点分治了 但是我们对于每个路径有两个性质就是(li,wi)(l_i,w_i) ...

最新文章

  1. 【软件测试培训】了解jmeter分布式测试
  2. C#经典再现——《C#本质论》
  3. 博客园模板 样式优化
  4. RabbitMQ之RPC实现
  5. KVM — 开启嵌套虚拟化
  6. nodejs 转换long到unsigned long(NXT)
  7. java AC自动机
  8. 深入浅出MFC文档/视图架构之文档模板
  9. 如何利用 Webshell 诊断 EDAS Serverless 应用
  10. apache httpclient 工具类_使用HttpClient进行服务的远程调用
  11. 计算机博士复试英语自我介绍,博士生复试自我介绍的英文
  12. Activiti实战. 1.3Activiti的特点
  13. 要是面试官再问我volatile,我就这么答
  14. [转]冰山一角 管窥中国互联网的地下世界
  15. 锯齿波FMCW雷达目标检测原理
  16. “数据分析”岗位分析
  17. Smbus host controller not enabled Assuming drive cache : write through
  18. 记2020年(第16届)湖南ACM省赛
  19. 利用Python导入股票列表
  20. 电脑卡顿,终于解决了多年的电脑卡顿问题

热门文章

  1. C# 基础知识和VS2010的小技巧总汇(2)[转]
  2. 2012最新75款好看的英文字体免费下载【中篇】
  3. Ubuntu 通过Deb 安装 MySQL 5.5 [转载]
  4. 员工借款及还款场景演练
  5. ie代理配置错误_电缆厂组织结构图的7个常犯错误!
  6. docker和k8s发展史--理解oci/cri/cni/docker swarm/containerd/runc/dockershim
  7. 从零开始做一个工业级别的实时换脸程序
  8. (137)FPGA面试题-Verilog HDL中function和task的区别(一)
  9. (65)FPGA面试题-状态机编码选择原则?
  10. (24)VHDL实现与或非(行为描述)