HDU 1166 —— 敌兵布阵 【树状数组 or 线段树】

http://acm.hdu.edu.cn/showproblem.php?pid=1166

需求:

  1.点修改

  2.区间求和

标准的BIT(二叉索引树,又名树状数组)问题,当然也可以用最基础的仅支持“点修改”的线段树来解决!

线段树版本:

#include <cstdio>
#include <iostream>
#define INF 0x3f3f3f3f
using namespace std;

const int MAXN = 65536 + 5; // 65536 是最小的大于等于50000的2^k, 这里如果写成50000 + 5 可是要超时的!
int sumv[MAXN*2-1];
int n, N;

int ql, qr;
int query(int o, int l, int r)
{
    if(qr < l || r < ql)    return 0;
    if(ql <= l && r <= qr)    return sumv[o];

    int m = (l + r) >> 1, ret = 0;
    ret += query((o << 1) + 1, l, m);
    ret += query((o << 1) + 2, m + 1, r);
    return ret;
}

void update(int k, int v)
{
    k += N-1;
    sumv[k] = v;
    while(k>0) {
        k = (k-1) >> 1;
        sumv[k] = sumv[(k << 1) + 1] + sumv[(k << 1) + 2];
    }
}

char s[20];

int main ()
{
    int T, p, q, v;
    scanf("%d", &T);
    for(int kase = 1; kase <= T; kase++) {
        scanf("%d", &n);

        N = 1;
        while(N < n)    N <<= 1; // 找到最小的大于等于n的2^k,因为叶子节点至少要放得下n个数字

        int tot = (1<<N)-1;
        for(int i=0; i<tot; i++)    sumv[i] = 0; // 初始化

        // 构建线段树 O(nlgn)
//      for(int i=0; i<n; i++) {
//          scanf("%d", &v);
//          update(i, v);
//      }

        // 构建线段树 O(n)
        for(int i=0; i<n; i++) {
            scanf("%d", &sumv[N-1+i]);
        }
        for(int i=N-2; i>=0; i--) {
            sumv[i] = sumv[(i << 1) + 1] + sumv[(i << 1) + 2];
        }

        printf("Case %d:\n", kase);
        while(scanf("%s", s) != EOF && s[0] != ‘E‘) {
            scanf("%d%d", &p, &q);
            if(s[0] == ‘A‘) {
                update(p-1, sumv[p-1+N-1] + q);

            } else if(s[0] == ‘S‘) {
                update(p-1, sumv[p-1+N-1] - q);
            } else {
                ql = p-1;
                qr = q-1;
                printf("%d\n", query(0, 0, N-1));
            }
        }
    }
    return 0;
} 

树状数组(BIT)版本:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#define INF 0x3f3f3f3f
using namespace std;

const int MAXN = 50000 + 5;
int C[MAXN];
char s[20];
int n;

int query(int x)
{
    int ret = 0;
    while(x) {
        ret += C[x];
        x -= x&(-x);
    }
    return ret;
}

void add(int k, int d)
{
    while(k <= n) {
        C[k] += d;
        k += k&(-k);
    }
}

int main ()
{
    int T, p, q, x;
    scanf("%d", &T);
    for(int kase = 1; kase <= T; kase++) {
        scanf("%d", &n);

        for(int i=1; i<=n; i++) {
            scanf("%d", &x);
            add(i, x);
        }

        printf("Case %d:\n", kase);
        while(scanf("%s", s) != EOF && s[0] != ‘E‘) {
            scanf("%d%d", &p, &q);
            if(s[0] == ‘A‘) {
                add(p, q);
            } else if(s[0] == ‘S‘) {
                add(p, -q);
            } else {
                printf("%d\n", query(q) - query(p-1));
            }
        }
        memset(C, 0, sizeof(C));
    }
    return 0;
} 
时间: 2024-08-24 09:55:32

HDU 1166 —— 敌兵布阵 【树状数组 or 线段树】的相关文章

hdu 1166:敌兵布阵(树状数组,练习题)

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 37773    Accepted Submission(s): 15923 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就

HDU 1166 敌兵布阵 (线段树 &amp; 树状数组)

敌兵布阵 Time Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u SubmitStatus 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的

[HDU 1166 敌兵布阵] 线段树 或 树状数组

1 #include<iostream> 2 #include<cstdio> 3 #include<memory.h> 4 using namespace std; 5 int n,C[50005]; 6 //-------------------------- 7 int lowbit(int x){ 8 return x&-x; 9 } 10 int sum(int x){ 11 int ret=0; 12 while(x>0){ 13 ret+=C

HDU 1166 敌兵布阵 (我的树状数组加线段树点修改模板)

思路:本题因为是点修改,所以我们可以用线段树或者是树状数组了.线段树的基本操作我在我的代码中会具体体现,关键是要理解下面这幅图,具体的思想大家可以去看看其他的资料 线段树AC代码: #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; #define N 50005 int num

【线段树I:母题】hdu 1166 敌兵布阵

[线段树I:母题]hdu 1166 敌兵布阵 题目链接:hdu 1166 敌兵布阵 题目大意 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又開始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况. 因为採取了某种先进的监測手段,所以每一个工兵营地的人数C国都掌握的一清二楚,每一个工兵营地的人数都有可能发生变动.可能添加或降低若干人手,但这些都逃只是C国的监视. 中央情报局要研究敌人到底演习什么战术,所以

【线段树】hdu 1166 敌兵布阵

[线段树]hdu 1166 敌兵布阵 题目链接:hdu 1166 敌兵布阵 题目大意 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视. 中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时

hdu 1166 敌兵布阵 线段树 点更新

// hdu 1166 敌兵布阵 线段树 点更新 // // 这道题裸的线段树的点更新,直接写就可以了 // // 一直以来想要进线段树的坑,结果一直没有跳进去,今天算是跳进去吧, // 虽然十分简单,十分的水,继续加油 #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits

HDU 1166 敌兵布阵(线段树)

Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视. 中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少

HDU 1166 敌兵布阵 (线段树 单点更新)

题目链接 线段树掌握的很差,打算从头从最简单的开始刷一波, 嗯..就从这个题开始吧! 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <cstdlib> 6 #include <algorithm> 7 const int maxn = 50000+10; 8 using namespace std

HDU 1166 敌兵布阵(线段树的初步应用2)

HDU  1166  敌兵布阵 Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视. 中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工