hdu 1166 敌兵布阵

来源:互联网 发布:手机版工程造价软件 编辑:程序博客网 时间:2024/06/05 04:23

点击打开链接hdu 1166

思路: 线段树单点更新

分析:

1 题目给定n个兵营的人数,现在有三种操作

 (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个营地的总人数;

2 最简单的线段树单点更新的题目


代码:

/************************************************ * By: chenguolin                               *  * Date: 2013-09-01                             * * Address: http://blog.csdn.net/chenguolinblog * ************************************************/#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define Lson(x) (x<<1)#define Rson(x) (Lson(x)|1)#define Mid(x,y) ((x+y)>>1)#define Sum(x,y) (x+y)const int N = 10;const int MAXN = 50010;int n;int num[MAXN];struct Node{    int left;    int right;    int sum;};Node node[4*MAXN];void push_up(int pos){    node[pos].sum = Sum(node[Lson(pos)].sum,node[Rson(pos)].sum);}void init(int left , int right , int pos){    node[pos].left = left;    node[pos].right = right;    if(left == right){       node[pos].sum = num[left];       return;    }    int x = Mid(left , right);    init(left , x , Lson(pos));    init(x+1 , right , Rson(pos));    push_up(pos);}void update(int index , int val , int pos){    if(node[pos].left == node[pos].right){        node[pos].sum += val;        return;    }    int x = Mid(node[pos].left , node[pos].right);    if(index <= x)        update(index , val , Lson(pos));    else        update(index , val , Rson(pos));    push_up(pos);}int query(int left , int right , int pos){    if(node[pos].left == left && node[pos].right == right)        return node[pos].sum;    int x = Mid(node[pos].left , node[pos].right);    if(right <= x)        return query(left , right , Lson(pos));    else if(left > x)        return query(left , right , Rson(pos));    else        return query(left , x , Lson(pos))+query(x+1 , right , Rson(pos));}void input(){    char str[N];    scanf("%d" , &n);    for(int i = 1 ; i <= n ; i++)        scanf("%d" , &num[i]);    init(1 , n , 1);    getchar();    int x , y;    while(scanf("%s" , str) && str[0] != 'E'){        scanf("%d%d%*c" , &x , &y);        if(str[0] == 'Q')            printf("%d\n" , query(x , y , 1));        else if(str[0] == 'A')            update(x , y , 1);        else            update(x , -y , 1);    }}int main(){    int Case;    int cas = 1;    scanf("%d" , &Case);    while(Case--){        printf("Case %d:\n" , cas++);        input();    }    return 0;}


思路:树状数组
分析:
1 对于区间求和的问题一般利用树状数组比线段树来的方便
2 树状数组建立就是在输入数据的时候做n次的update()。

代码:

/************************************************ By: chenguolin                               * * Date: 2013-08-20                             ** Address: http://blog.csdn.net/chenguolinblog ************************************************/#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int MAXN = 50010;int n;int treeNum[MAXN];int lowbit(int x){    return x&(-x);}int getSum(int x){    int sum = 0;    while(x){        sum += treeNum[x];        x -= lowbit(x);    }    return sum;}void add(int x , int val){    while(x < MAXN){         treeNum[x] += val;         x += lowbit(x);    }}void solve(){    int x , y;    char str[10];    memset(treeNum , 0 , sizeof(treeNum));    for(int i = 1 ; i <= n ; i++){        scanf("%d%*c" , &x);        add(i , x);    }    while(scanf("%s" , str) && str[0] != 'E'){        scanf("%d%d%*c" , &x , &y);        if(str[0] == 'Q'){           int ans = getSum(y);            ans -= getSum(x-1);           printf("%d\n" , ans);        }         else if(str[0] == 'A'){           add(x , y);         }         else{            add(x , -y);         }     }}int main(){    int cas = 1;    int Case;    scanf("%d" , &Case);    while(Case--){         printf("Case %d:\n" , cas++);          scanf("%d" , &n);         solve();    }    return 0;}



原创粉丝点击