• hdu1166(线段树单点更新、查询)


    题目链接:http://hdu.hustoj.com/showproblem.php?pid=1166

    题意:

      第一行一个整数T,表示有T组数据。
      每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。
      接下来每行有一条命令,命令有4种形式:
      (1) Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30)
      (2)Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30);
      (3)Query i j ,i和j为正整数,i<=j,表示询问第i到第j个营地的总人数;
      (4)End 表示结束,这条命令在每组数据最后出现;
      每组数据最多有40000条命令

    思路:

      典型的线段树单点更新+查询

    代码:

      1 #include <iostream>
      2 using namespace std;
      3 
      4 const int maxn = 50010;
      5 int segTree[maxn * 4];  //1-n子区间数量不超过4*n
      6 
      7 
      8 void pushUp(int root)   //更新父节点值
      9 {
     10     segTree[root] = segTree[root * 2] + segTree[root * 2 + 1];  //这题的操作是求和
     11 }
     12 
     13 void build(int root, int left, int right)  //建立线段树
     14 {
     15     if (left == right) //到了叶子节点就输入叶子结点的值
     16     {
     17         cin >> segTree[root];
     18         return;
     19     }
     20 
     21     int mid = (left + right) / 2;
     22 
     23     //递归建立左子树和右子树
     24     build(root * 2, left, mid);
     25     build(root * 2 + 1, mid + 1, right);
     26 
     27     //每次更新父节点值
     28     pushUp(root);
     29 }
     30 
     31 void update(int root, int p, int add, int left, int right) //单节点更新,p为待更新节点下标,add为需增加或减少的值
     32 {
     33     if (left == right)  //找到单节点就更新
     34     {
     35         segTree[root] += add;
     36         return;
     37     }
     38 
     39     //二分查找指定节点
     40     int mid = (left + right) / 2;
     41     if (p <= mid)
     42     {
     43         update(root * 2, p, add, left, mid);
     44     }
     45     else
     46     {
     47         update(root * 2 + 1, p, add, mid + 1, right);
     48     }
     49 
     50     //每次更新父节点值
     51     pushUp(root);
     52 }
     53 
     54 int query(int root, int q_left, int q_right, int now_left, int now_right)  //查询区间
     55 {
     56     if (q_left <= now_left && q_right >= now_right)  //当前节点区间包含在查询区间内
     57     {
     58         return segTree[root];
     59     }
     60 
     61     int mid = (now_left + now_right) / 2;
     62     int sum = 0;
     63     if (q_left <= mid)
     64     {
     65         sum += query(root * 2, q_left, q_right, now_left, mid);
     66     }
     67     if (q_right > mid)
     68     {
     69         sum += query(root * 2 + 1, q_left, q_right, mid + 1, now_right);
     70     }
     71     return sum;
     72 }
     73 
     74 int main()
     75 {
     76     ios::sync_with_stdio(false);    //取消cin于stdin的同步,不加这句除非用scanf和printf,不然会TLE
     77     int t, n;
     78     char op[10];
     79     cin >> t;
     80     for (int i = 1; i <= t; i++)
     81     {
     82         cout << "Case " << i << ":" << endl;
     83         cin >> n;
     84         build(1, 1, n);
     85         while(cin >> op)
     86         {
     87             if (op[0] == 'E')
     88             {
     89                 break;
     90             }
     91             int a, b;
     92             cin >> a >> b;
     93             if (op[0] == 'Q')   //询问
     94             {
     95                 int ans = query(1, a, b, 1, n);
     96                 cout << ans << endl;
     97             }
     98             else if (op[0] == 'S')  //
     99             {
    100                 update(1, a, -b, 1, n);
    101             }
    102             else if (op[0] == 'A')  //
    103             {
    104                 update(1, a, b, 1, n);
    105             }
    106         }
    107     }
    108     return 0;
    109 }

    体会:

      线段树的入门题,加深对线段树的理解和熟悉一下相关操作的代码编写。

  • 相关阅读:
    InfoPath 发布表单到SharePoint库报错
    在log4net中控制nhibernate输出
    微信扫一扫(wx.scanQRCode)功能新手可能遇到的问题
    3.Zookeeper的安装和配置(集群模式)
    1.配置HDFS HA (高可用)
    2.Zookeeper工作原理(详细)
    1.Zookeeper 定义与工作原理
    js 获取元素的几种方法
    弹出层居中
    XUACompatible
  • 原文地址:https://www.cnblogs.com/friend-A/p/9365313.html
Copyright © 2020-2023  润新知