• hdu 1166 敌兵布阵 (线段树、单点更新)


    敌兵布阵
    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 112150    Accepted Submission(s): 47034


    Problem Description
    C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。
    中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:“Tidy,马上汇报第3个营地到第10个营地共有多少人!”Tidy就要马上开始计算这一段的总人数并汇报。但敌兵营地的人数经常变动,而Derek每次询问的段都不一样,所以Tidy不得不每次都一个一个营地的去数,很快就精疲力尽了,Derek对Tidy的计算速度越来越不满:"你个死肥仔,算得这么慢,我炒你鱿鱼!”Tidy想:“你自己来算算看,这可真是一项累人的工作!我恨不得你炒我鱿鱼呢!”无奈之下,Tidy只好打电话向计算机专家Windbreaker求救,Windbreaker说:“死肥仔,叫你平时做多点acm题和看多点算法书,现在尝到苦果了吧!”Tidy说:"我知错了。。。"但Windbreaker已经挂掉电话了。Tidy很苦恼,这么算他真的会崩溃的,聪明的读者,你能写个程序帮他完成这项工作吗?不过如果你的程序效率不够高的话,Tidy还是会受到Derek的责骂的.
     

    Input
    第一行一个整数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条命令
     

    Output
    对第i组数据,首先输出“Case i:”和回车,
    对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数保持在int以内。
     

    Sample Input
    1
    10
    1 2 3 4 5 6 7 8 9 10
    Query 1 3
    Add 3 6
    Query 2 7
    Sub 10 2
    Add 6 3
    Query 3 10
    End
     

    Sample Output
    Case 1:
    6
    33
    59

    1 PS:TLE两次,有点伤心,加了 “ios::sync_with_stdio(false);” 输入、输出还是没有scanf、printf:快

    分析:

    1 数据结构:线段树

    核心代码:

     1 void build_tree(int i, int l, int r)
     2 {
     3     node[i].l = l;
     4     node[i].r = r;
     5     node[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         node[r].value += b;
    20         return ;
    21     }
    22     node[r] += b;
    23     return ;
    24 }
    25 
    26 void query_tree(int i, int l, int r)
    27 {
    28     if (node[i].l == l && node[i].r == r)
    29     {
    30         ans += node[i].value;
    31         return ;
    32     }
    33     i = i <<1;
    34     if (l <= node[i].r)
    35     {
    36         if (r <= node[i].r) query_tree(i, l, r);
    37         else query_tree(i, l, node[r].r);
    38     }
    39     ++ i;
    40     if (r >= node[i].l)
    41     {
    42         if (l >= node[i].l) query_tree(i, l, r);
    43         else query_tree(i, node[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<<19;
     12 const int MAXN = 1e5 + 10;
     13 int T, cnt = 1, temp[40010], pos, n, g, pre[MAXN], 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_add_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_add_tree(r>>1, b);
     43 }
     44 
     45 void update_sub_tree(int r, int b)
     46 {
     47     if (r == 1)
     48     {
     49         P[r].value -= b;
     50         return ;
     51     }
     52     P[r].value -= b;
     53     update_sub_tree(r>>1, b);
     54 }
     55 
     56 void query_tree(int i, int l, int r)
     57 {
     58     if (P[i].l == l && P[i].r == r)
     59     {
     60         ans += P[i].value;
     61         return ;
     62     }
     63     i = i<<1;
     64     if (l <= P[i].r)
     65     {
     66         if (r <= P[i].r) query_tree(i, l, r);
     67         else query_tree(i, l, P[i].r);
     68     }
     69     ++ i;
     70     if (r >= P[i].l)
     71     {
     72         if (l >= P[i].l) query_tree(i, l, r);
     73         else query_tree(i, P[i].l, r);
     74     }
     75 }
     76 
     77 int main () {
     78     scanf ("%d", &T);
     79     //ios::sync_with_stdio(false);
     80     while (T --) {
     81         pos = 0;
     82         scanf("%d", &n);
     83         build_tree(1, 1, n);
     84         for (int i = 1; i <= n; ++ i)
     85         {
     86             scanf("%d", &g);
     87             update_add_tree(pre[i], g);
     88         }
     89         char op[10];
     90         int a, b;
     91         while (~scanf("%s", op))
     92         {
     93             if (op[0] == 'E') break;
     94             //cin >>a >>b;
     95             scanf("%d%d", &a, &b);
     96             if (op[0] == 'Q')
     97             {
     98                 ans = 0;
     99                 query_tree(1, a, b);
    100                 temp[pos ++] = ans;
    101             }
    102             else if (op[0] == 'A')
    103             {
    104                 update_add_tree(pre[a], b);
    105             }
    106             else
    107             {
    108                 update_sub_tree(pre[a], b);
    109             }
    110         }
    111         printf("Case %d:
    ", cnt ++);
    112         for (int i = 0; i < pos; ++ i)
    113         {
    114             printf("%d
    ", temp[i]);
    115         }
    116     }
    117     return 0;
    118 }
  • 相关阅读:
    《数据结构第一章复习》
    《图的基本操作》
    《矩阵的一些基本操作》
    <矩阵的基本操作:矩阵相加,矩阵相乘,矩阵转置>
    《两个二维数组(矩阵)相乘》
    C#隐藏与显示系统任务栏和开始菜单栏按钮
    C#通过窗体属性缩小一定尺寸时,无法再缩小窗体尺寸问题
    C#一个窗体调用另一个窗体的方法
    C#异步线程
    C#中MessageBox.Show问题(让提示窗口不显示在任务栏中)
  • 原文地址:https://www.cnblogs.com/GetcharZp/p/9010513.html
Copyright © 2020-2023  润新知