数据结构中的线段树处理的主要是一些对于区间的操作,比一般的方式要快很多(logn)
线段树的存储可以定义一个数据结构
struct segt{ int rt;根节点 int ls,rs//区间的左右端点 int val ;//要维护的值 /*其他*/ }tree[maxn];
线段树是一种完全二叉树,用tree[ rt ] 存储的话 ,左儿子为 tree[ rt << 1 ] 右儿子为 tree[ rt << 1 | 1 ]
线段树将一个区间通过二分的方式逐渐的分成一些单元区间,每次划分维护 左右端点,根结点的值
每次操作是对这些单元区间进行操作
比如1到16吧,最初的区间根节点(rt)为1,最初的区间可以划分成左子树和右子树,
根结点分别为2(rt<<1)和3(rt<<1|1)代表的区间分别为 1 到 8 (rt = 2)和9到16(rt = 3),
1到8这个区间再继续划分,左子树根结点4,区间1到4,右子树根结点5,区间5到8,依次类推
直到每个区间只有一个数字
ac的代码
# include <cstdio> # include <iostream> # include <cstring> # include <algorithm> using namespace std; const int maxn=5e4+5; int sum[maxn*4]; void build(int root,int l,int r){ if(l==r) { scanf("%d",&sum[root]); return ; } build(root<<1,l,(l+r)/2); build(root<<1|1,(l+r)/2+1,r); sum[root]=sum[root<<1]+sum[root<<1|1]; } void update(int p,int add,int l,int r,int root){ if(l==r){ sum[root]+=add; return; } if(p<=(l+r)/2) update(p,add,l,(l+r)/2,root<<1); else update(p,add,(l+r)/2+1,r,root<<1|1); sum[root]=sum[root<<1]+sum[root<<1|1]; } int query(int L,int R,int l,int r,int root){ if(L<=l&&r<=R) return sum[root]; int cnt=0; if(L<=(l+r)/2) cnt+=query(L,R,l,(l+r)/2,root<<1); if(R>(l+r)/2) cnt+=query(L,R,(l+r)/2+1,r,root<<1|1); return cnt; } int main(){ int t,l=0; scanf("%d",&t); while(l<t){ int n; scanf("%d",&n); build(1,1,n); char qu[10]; printf("Case %d: ",++l); while(scanf("%s",qu)){ if(qu[0]=='E') break; int a,b; scanf("%d %d",&a,&b); if(qu[0]=='A') update(a,b,1,n,1); if(qu[0]=='S') update(a,-b,1,n,1); if(qu[0]=='Q') { int ans=query(a,b,1,n,1); printf("%d ",ans); } } } return 0; }