HDU1166 敌兵布阵 [线段树模板]
题意:在序列中修改单点和查询区间和
#include<iostream> #include<cstdio> #include<cstring> #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const int maxn=50005*4; int sum[maxn<<2],add[maxn<<2];//sum求和,add懒惰标记 int a[maxn]={0},n=50005;//存原数组数据下标[1,n] //更新节点信息,这里是求和 void pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } //建树 void pushdown(int rt,int ln,int rn) {//ln,rn为左子树,右子树的数量 if(add[rt])//下推标记 { add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; sum[rt<<1]+=add[rt]*ln; sum[rt<<1|1]+=add[rt]*rn; add[rt]=0;//清除本节点标记 } } void build(int l,int r,int rt)//rt表示当前节点编号 { if(l==r) { sum[rt]=a[l]; return; } int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); pushup(rt); } //点修改a[L]+=c; //比如update(a,-b,1,n,1);//修改a点的值,减去b,当前节点区间是1到n,起始点是1 void update(int L,int c,int l,int r,int rt) {//l,r当前节点区间,rt当前节点编号,L需要修改的节点,c修改的值 if(l==r) { sum[rt]+=c; return; } int m=(l+r)>>1; //根据条件判断调用左子树还是右子树 if(L<=m) update(L,c,l,m,rt<<1); else update(L,c,m+1,r,rt<<1|1); pushup(rt);//子节点更新,所以本节点也需要更新 } //区间修改a[r,t]+=c ////比如query(a,b,1,n,1))查询a b之间的和,当前节点区间是1到n,起始点是1 void update_(int L,int R,int c,int l,int r,int rt) {//L,R表示操作区间,l,r表示当前节点区间,rt表示当前节点编号 if(L<=l&&r<=R)//遍历的区间在操作区间内 { sum[rt]+=c*(r-l+1); add[rt]+=c; return; } int m=(l+r)>>1; pushdown(rt,m-l+1,r-m); if(L<=m) update_(L,R,c,l,m,rt<<1); if(R>m) update_(L,R,c,m+1,r,rt<<1|1); pushup(rt); } //区间查询 a[l,r]的和 //下推标记函数 int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { return sum[rt]; } int m=(l+r)>>1; pushdown(rt,m-l+1,r-m); int ans=0; if(L<=m) ans+=query(L,R,l,m,rt<<1); if(R>m) ans+=query(L,R,m+1,r,rt<<1|1); return ans; } int main() { int t,cnt=1; scanf("%d",&t); while(t--) { memset(a,0,sizeof(a)); memset(sum,0,sizeof(sum)); memset(add,0,sizeof(add)); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); printf("Case %d:\n",cnt++); char str[20]; while(scanf("%s",str)&&str[0]!='E') { int a,b; scanf("%d%d",&a,&b); if(str[0]=='Q') { query(a,b,1,n,1); } if(str[0]=='S') update(a,-b,1,n,1);//修改a点的值,减去b,当前节点区间是1到n,起始点是1 if(str[0]=='A') update(a,b,1,n,1); if(str[0]=='Q') printf("%d\n",query(a,b,1,n,1));//查询a b之间的和,当前节点区间是1到n,起始点是1 } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步