nyoj 116 士兵杀敌(二)(线段树、单点更新)

士兵杀敌(二)

时间限制: 1000 ms  |  内存限制:65535 KB
难度: 5
 
描述

南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的。

小工是南将军手下的军师,南将军经常想知道第m号到第n号士兵的总杀敌数,请你帮助小工来回答南将军吧。

南将军的某次询问之后士兵i可能又杀敌q人,之后南将军再询问的时候,需要考虑到新增的杀敌数。

 

 
输入
只有一组测试数据
第一行是两个整数N,M,其中N表示士兵的个数(1<N<1000000),M表示指令的条数。(1<M<100000)
随后的一行是N个整数,ai表示第i号士兵杀敌数目。(0<=ai<=100)
随后的M行每行是一条指令,这条指令包含了一个字符串和两个整数,首先是一个字符串,如果是字符串QUERY则表示南将军进行了查询操作,后面的两个整数m,n,表示查询的起始与终止士兵编号;如果是字符串ADD则后面跟的两个整数I,A(1<=I<=N,1<=A<=100),表示第I个士兵新增杀敌数为A.
输出
对于每次查询,输出一个整数R表示第m号士兵到第n号士兵的总杀敌数,每组输出占一行
样例输入
5 6
1 2 3 4 5
QUERY 1 3
ADD 1 2
QUERY 1 3
ADD 2 3
QUERY 1 2
QUERY 1 5
样例输出
6
8
8
20
1 PS:虽然在一定程度上加上ios::sync_with_stdio(false);可以提高代码的cin、cout速率,
2 但建议用scanf、printf,因为cin、cout还是没有scanf、printf快???

分析:

1 因为起数据量很大,普通的遍历会TLE所以使用数据结构--线段树
2 (因为线段树的区域求和不用一个一个的相加,而是其内部已经完成了一定区域的求和工作)

线段树模板:

 1 void build_tree(int i, int l, int r)
 2 {
 3     P[i].l = l;
 4     P[i].r = r;
 5     P[i].value = 0;
 6     if (l == r)
 7     {
 8         pre[l] = i;
 9         return ;
10     }
11     build_tree(i<<1, l, (int)(floor(l + r) / 2.0));
12     build_tree((i<<1) + 1, (int)(floor(l + r) / 2.0) + 1, r);
13 }
14 
15 void update_tree(int r, int b)
16 {
17     if (r == 1)
18     {
19         P[r].value += b;
20         return;
21     }
22     P[r].value += b;
23     update_tree(r / 2, b);
24 }
25 
26 void query_tree(int i, int l, int r)
27 {
28     if (P[i].l == l && P[i].r == r)
29     {
30         ans += P[i].value;
31         return ;
32     }
33     i = i<<1;
34     if (l <= P[i].r)
35     {
36         if (r <= P[i].r) query_tree(i, l, r);
37         else query_tree(i, l, P[i].r);
38     }
39     ++ i;
40     if (r >= P[i].l)
41     {
42         if (l >= P[i].l) query_tree(i, l, r);
43         else query_tree(i, P[i].l, r);
44     }
45 }

C/C++代码实现(AC):

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <cmath>
 6 #include <stack>
 7 #include <map>
 8 #include <queue>
 9 
10 using namespace std;
11 const int MAXNODE = 1<<21; // = 2097152
12 const int MAXN = 2e6 + 10;
13 int n, m, pre[MAXN], temp, ans;
14 
15 struct node
16 {
17     int l, r, value;
18 }P[MAXNODE];
19 
20 void build_tree(int i, int l, int r)
21 {
22     P[i].l = l;
23     P[i].r = r;
24     P[i].value = 0;
25     if (l == r)
26     {
27         pre[l] = i;
28         return ;
29     }
30     build_tree(i<<1, l, (int)(floor(l + r) / 2.0));
31     build_tree((i<<1) + 1, (int)(floor(l + r) / 2.0) + 1, r);
32 }
33 
34 void update_tree(int r, int b)
35 {
36     if (r == 1)
37     {
38         P[r].value += b;
39         return;
40     }
41     P[r].value += b;
42     update_tree(r / 2, b);
43 }
44 
45 void query_tree(int i, int l, int r)
46 {
47     if (P[i].l == l && P[i].r == r)
48     {
49         ans += P[i].value;
50         return ;
51     }
52     i = i<<1;
53     if (l <= P[i].r)
54     {
55         if (r <= P[i].r) query_tree(i, l, r);
56         else query_tree(i, l, P[i].r);
57     }
58     ++ i;
59     if (r >= P[i].l)
60     {
61         if (l >= P[i].l) query_tree(i, l, r);
62         else query_tree(i, P[i].l, r);
63     }
64 }
65 
66 int main() {
67     ios::sync_with_stdio(false);
68     cin >>n >>m;
69     build_tree(1, 1, n);
70     for (int i=1; i<=n; ++i)
71     {
72         cin >>temp;
73         update_tree(pre[i], temp);
74     }
75     string op;
76     int a, b;
77     while(m --)
78     {
79         cin >>op >>a >>b;
80         if (op == "QUERY")
81         {
82             ans = 0;
83             query_tree(1, a, b);
84             cout <<ans <<endl;
85         }
86         else
87         {
88             update_tree(pre[a], b);
89         }
90     }
91     return 0;
92 }

 

类似题:hdoj 1166 敌兵布阵

转载于:https://www.cnblogs.com/GetcharZp/p/9010406.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值