题目描述:
A国在边境线设置N个兵营。C国通过先进的的手段对A国的每个兵营的人数都掌握的一清二楚。每个兵营可以增加人数或减少人数。
输入:
第一行包含一个整数T,表示有T组测试数据。每组数据的第一行都包含一个整数N(N≤50000),表示有N个兵营。接下来有N个正整数,第i个整数ai表示第i个兵营的人数(1≤ai≤50)。再接下来每行都有一个命令,每组数据最多有40000条命令,命令有4种形式:
(1)Add i j,表示在第i个兵营增加j个人(j ≤30)。
(2)Sub i j,表示在第i个兵营减少j个人(j ≤30)。
(3)Query i j,i ≤ j,表示查询第i~j个营地的总人数;
(4)End,表示结束,在每组数据的最后出现。
输出:
对第i组数据,首先单行输出“Case i:”,然后对每个Query都单行输出查询区间的总人数。
输入样例: 3
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
输出样例:
Case 1:
6
33
59
题解:本题包括点更新和区间查询,可以采用线段数组解决。
#include<cstdio>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=55555;
int sum[maxn<<2];
void PushUP(int rt){//更新和值
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt){//构建线段树
if(l==r){
scanf("%d",&sum[rt]);
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUP(rt);
}
void update(int p,int add,int l,int r,int rt){//单点更新
if (l==r){
sum[rt]+=add;
return ;
}
int m=(l+r)>>1;
if(p<=m) update(p,add,lson);
else update(p,add,rson);
PushUP(rt);
}
//int query(int L,int R,int l,int r,int rt)//区间查询1
//{
// if (L<=l&&r<=R)//覆盖
// return sum[rt];
// int m=(l+r)>>1;
// int ret=0;
// if(L<=m) ret+=query(L,R,lson);
// if(R>m) ret+=query(L,R,rson);
// return ret;
//}
int query(int L,int R,int l,int r,int rt){//区间查询2
if(L==l&&r==R)//判断条件为相等
return sum[rt];
int m=(l+r)>>1;
if(R<=m)
return query(L,R,lson);
else if(L>m)
return query(L,R,rson);
else return query(L,m,lson)+query(m+1,R,rson);
}
int main(){
int T,n;
scanf("%d",&T);
for (int cas=1;cas<=T;cas++){
printf("Case %d:\n",cas);
scanf("%d",&n);
build(1,n,1);
char op[10];
while(scanf("%s",op)){
if(op[0]=='E') break;
int i,j;
scanf("%d%d",&i,&j);
if(op[0]=='Q') printf("%d\n",query(i,j,1,n,1));
else if(op[0]=='S') update(i,-j,1,n,1);
else update(i,j,1,n,1);
}
}
return 0;
}