随笔 - 97, 文章 - 22, 评论 - 81, 引用 - 0
数据加载中……

HDU 1166 敌兵布阵

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166
/*
题意:
    给定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 表示结束,这条命令在每组数据最后出现

解法:
    树状数组 或者 线段树

思路:
    典型的树状数组模板题,Add和Sub是同一个操作,Sub就是Add一个负的值,只
是Sub之前先要判断这个点有没有这么多,询问就是利用树状数组的成段求和。
*/


#include 
<iostream>

using namespace std;

#define maxn 1000010

int c[maxn], n;
int a[maxn];
char ch[100];

int lowbit(int x) {
    
return x & (-x);
}


void Add(int x, int add) {
    
while(x <= n) {
        c[x] 
+= add;    
        x 
+= lowbit(x);
    }

}


int sum(int x) {
    
int s = 0;
    
while(x > 0{
        s 
+= c[x];
        x 
-= lowbit(x);
    }

    
return s;
}


int main() {
    
int t, as, bs, i, q = 1;
    scanf(
"%d"&t);
    
while(t--{
        scanf(
"%d"&n);
        memset(c, 
0sizeof(c));
        
for(i = 1; i <= n ;i++{
            scanf(
"%d"&a[i]);
            Add(i, a[i]);
        }

        printf(
"Case %d:\n", q++);
        
while(scanf("%s" , ch) != EOF) {
            
if(!strcmp(ch, "End"))
                
break;
            
else if(!strcmp(ch, "Query")) {
                scanf(
"%d%d"&as&bs);
                printf(
"%d\n", sum(bs) - sum(as - 1));
            }
else if(!strcmp(ch, "Add")) {
                scanf(
"%d%d"&as&bs);
                Add(
as, bs);
            }
 else if(!strcmp(ch, "Sub")) {
                scanf(
"%d%d"&as&bs);
                Add(
as-bs);
            }

        }

        
    }

}

posted on 2011-04-07 18:04 英雄哪里出来 阅读(1819) 评论(0)  编辑 收藏 引用 所属分类: 线段树树状数组


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理