线段树
区间和
http://oj.61coding.cn/problem.php?cid=1025&pid=0
#include<bits/stdc++.h> using namespace std; inline int read(){//读入优化 char ch; while((ch=getchar()) <'0' || ch>'9'); int res=ch-48; while((ch=getchar())>='0' && ch<='9') res = res*10+ch-48; return res; } const int N=1e5+5; int n,m; long long sum[N*4];//数组开到n的4倍 void updateTree(int k,int L,int R,int p,int v){//单点修改累加 if(R<p || L>p) return;// p不在区间范围 if(L==R && L==p){// 叶子节点 并且是p 累加v sum[k]+=v; return; } int mid=(L+R)/2; updateTree(k*2,L,mid,p,v);//递归左子树 updateTree(k*2+1,mid+1,R,p,v);//递归右子树 sum[k]=sum[k*2]+sum[k*2+1];//父节点=左子节点+右子节点 } long long queryTree(int k,int L,int R,int x,int y){//区间查询 if(y<L || x>R) return 0;//不在范围内退出 if(L>=x && R<=y) return sum[k];//在子范围返回当前节点数据 int mid=(L+R)/2; long long res=0; res=queryTree(k*2,L,mid,x,y);//在范围一部分,递归求左子树 res+=queryTree(k*2+1,mid+1,R,x,y);//在范围一部分,递归求右子树 return res;//返回左右子树和 } int main(){ n=read(),m=read(); for(int i=1;i<=m;i++){ int k=read(),L=read(),R=read(); if(k==0){ updateTree(1,1,n,L,R); } else{ printf("%lld\n",queryTree(1,1,n,L,R)); } } return 0; }
A Simple Problem with Integers
http://oj.61coding.cn/problem.php?cid=1025&pid=1
#include<bits/stdc++.h> using namespace std; inline int get(){//优化录入 char c; int sign=1; while((c=getchar())<'0' || c>'9'){ if(c=='-'){ sign=-1; } } int res=c-'0'; while((c=getchar())>='0' && c<='9'){ res=res*10+c-'0'; } return res*sign; } const int N=1e5+5; int n,m,a[N]; int add[N*4];//此数组存放未及时下放更新的数据 long long sum[N*4];//用数组存放的树 总节点数可能大于2N void buildTree(int k,int L,int R){//建树 if(L==R){//叶子节点存放对应数 sum[k]=a[L]; return; } int mid=L+R>>1; buildTree(k<<1,L,mid);//左子树 buildTree(k<<1|1,mid+1,R);//右子树 sum[k]=sum[k<<1]+sum[k<<1|1];//左右子节点和存放到当前树节点 } void addTree(int k,int L,int R,int v){//区间加值并更新 add[k]+=v;//单节点增加的值 sum[k]+=(long long)v*(R-L+1);//区间和加到本节点 } void pushdown(int k,int L,int R,int mid){//标记下放 if(add[k]==0) return;//子节点已经增加 不在增加 addTree(k<<1,L,mid,add[k]);//左子节点增加 addTree(k<<1|1,mid+1,R,add[k]);//右子节点增加 add[k]=0;//本节点清零 } long long queryTree(int k,int L,int R,int x,int y){//区间询问 if(L>=x && R<=y) return sum[k];//需要查询的范围在L-R范围内 //不完全在范围内 int mid=L+R>>1; long long res=0; pushdown(k,L,R,mid);//处理当前未下传节点 if(x<=mid) res+=queryTree(k<<1, L, mid,x,y);//查询左子树 if(mid<y) res+=queryTree(k<<1|1,mid+1,R,x,y);//查询右子树 return res; //返回左右子树和 } void modifyTree(int k,int L,int R,int x,int y,int v){ //如果修改范围大于L-R范围 只增加本次k节点 不更新子节点 if(L>=x && R<=y) return addTree(k,L,R,v); //部分范围 需要更新子节点 标记下传 int mid=L+R>>1; pushdown(k,L,R,mid); if(x<=mid) modifyTree(k<<1, L, mid,x,y,v);//更新左子节点 if(mid<y) modifyTree(k<<1|1,mid+1,R,x,y,v);//更新右子节点 sum[k]=sum[k<<1]+sum[k<<1|1];//返回左右子节点和 } int main(){ n=get(),m=get(); for(int i=1;i<=n;i++) a[i]=get(); buildTree(1,1,n); while(m--){ char op; int A,B,C; while((op=getchar()) =='Q' || op=='C'){ A=get(),B=get(); cout<<"m:"<<m<<",op:"<<op<<",A:"<<A<<",B:"<<B<<endl; if(op=='Q') printf("%lld\n",queryTree(1,1,n,A,B)); else modifyTree(1,1,n,A,B,get()); } } return 0; }
作者:newcode 更多资源请关注纽扣编程微信公众号

从事机器人比赛、机器人等级考试、少儿scratch编程、信息学奥赛等研究学习

浙公网安备 33010602011771号