这道题目的大体意思就是
输入第一个数m为测试案例的个数
然后输入一个数n
给你n个军团
当输入Query i,j的时候查询从第I个军团到第J个军团一共多少人
当输入Add I,J的时候就是吧第I个军团的人加上J个人
输入Sub I,J的时候把第I个军团的人减少J个人
输入
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<stdio.h> #include<string.h> const int N=66666; int a[N]; long long sum[N<<2]; void build(int root,int l,int r) { if(l==r) { sum[root]=a[l]; return; } int mid=(l+r)>>1; build(root<<1,l,mid); build(root<<1|1,mid+1,r); sum[root]=sum[root<<1]+sum[root<<1|1]; } void update1(int root,int L,int R,int i,int v) { if(L==R) { sum[root]+=v; return; } int mid=(L+R)>>1; if(i<=mid) update1(root<<1,L,mid,i,v); else update1(root<<1|1,mid+1,R,i,v); sum[root]=sum[root<<1]+sum[root<<1|1]; } void update2(int root,int L,int R,int i,int v) { if(L==R) { sum[root]-=v; return; } int mid=(L+R)>>1; if(i<=mid) update2(root<<1,L,mid,i,v); else update2(root<<1|1,mid+1,R,i,v); sum[root]=sum[root<<1]+sum[root<<1|1]; } long long querysum(int root,int L,int R,int l,int r) { if(l<=L&&r>=R) { return sum[root]; } int mid=(L+R)>>1; long long sum1=0; if(l<=mid) sum1+=querysum(root<<1,L,mid,l,r); if(r>mid) sum1+=querysum(root<<1|1,mid+1,R,l,r); return sum1; } int main() { int t,m; scanf("%d",&t); int cnt=1; while(t--) { scanf("%d",&m); printf("Case %d:\n",cnt++); for(int i=1;i<=m;i++) scanf("%d",&a[i]); build(1,1,m); char b[10]; int l,r,h; while(scanf("%s",b)&&strcmp(b,"End")!=0) { if(strcmp(b,"Query")==0) { scanf("%d%d",&l,&r); printf("%lld\n",querysum(1,1,m,l,r)); } if(!strcmp(b,"Add")) { scanf("%d%d%d",&l,&r); update1(1,1,m,l,r); } if(!strcmp(b,"Sub")) { scanf("%d%d%d",&l,&r); update2(1,1,m,l,r); } } } return 0; }
这道题目我刚开始犯了几个错误,这个就比较坑了一开始数组的开的太小的,提交上去就WA然后是因为那个输出Case的时候忘记换行了,结果就出现presentation error,瞬间就崩溃了,不过后来就改了过来。