【题解】「HDU1166」敌兵布阵(线段树)

Flower ·
更新时间:2024-11-10
· 807 次阅读

题面

【题目描述】
有nnn个营地,已知每个营地的人数,有四条命令:
(1)Add(1) Add(1)Add iii jjj,iii和jjj为正整数,表示第iii个营地增加jjj个人(jjj不超过303030)
(2)Sub(2)Sub(2)Sub iii jjj ,iii和jjj为正整数,表示第iii个营地减少jjj个人(jjj不超过303030);
(3)Query(3)Query(3)Query iii jjj ,iii和jjj为正整数,i≤ji\leq ji≤j,表示询问第iii到第jjj个营地的总人数;
(4)End(4)End(4)End 表示结束,这条命令在每组数据最后出现;
【输入格式】
第一行一个整数TTT,表示有TTT组数据。
每组数据第一行一个正整数N(N≤50000N \leq 50000N≤50000),表示敌人有N个工兵营地,接下来有NNN个正整数,第iii个正整数aia_iai​代表第iii个工兵营地里开始时有aia_iai​个人(1≤ai≤501 \leq a_i \leq 501≤ai​≤50)。
接下来每行有一条命令,最多400004000040000条。
【输出】
对第i组数据,首先输出“CaseCaseCase i:i:i:”和回车,
对于每个QueryQueryQuery询问,输出一个整数并回车,表示询问的段中的总人数,这个数保持在intintint以内。
【样例输入】

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 #define N 50010 using namespace std; int T,n,a[N],s[4*N]; //4倍n void built(int k,int l,int r) //建线段树 { if(l==r) {s[k]=a[l];return;} int mid=(l+r)/2; built(2*k,l,mid); built(2*k+1,mid+1,r); s[k]=s[k*2]+s[k*2+1]; } void update(int k,int l,int r,int x,int v) //单点更新 { if(l==r&&l==x){s[k]+=v;return;} //找到单点修改 if(xr) return; int mid=(l+r)/2; if(l<=x&&x<=mid) update(k*2,l,mid,x,v); if(mid+1<=x&&x<=r) update(k*2+1,mid+1,r,x,v); s[k]=s[k*2]+s[k*2+1]; //回溯,维护区间和 } int ask(int k,int l,int r,int x,int y) //区间查询 { if(yr) return 0; //不相交 if(x<=l&&r<=y) return s[k]; //包含 int mid=(l+r)/2; return ask(k*2,l,mid,x,y)+ask(k*2+1,mid+1,r,x,y); } int main(){ scanf("%d",&T); int count=1; while(count<=T) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); built(1,1,n); char s[10]; int x,y; printf("Case %d:\n",count); while(1) { scanf("%s",s); if(s[0]=='E') break; scanf("%d%d",&x,&y); if(s[0]=='A') update(1,1,n,x,y); if(s[0]=='S') update(1,1,n,x,-y); if(s[0]=='Q') printf("%d\n",ask(1,1,n,x,y)); } count++; } return 0; }
作者:_BOSS_



hdu 线段树

需要 登录 后方可回复, 如果你还没有账号请 注册新账号