思路
最近被大佬安排学习线段树,学到吐血。看了HH神对于线段树的讲解,忽然有所头绪。
今天敲了一道,写写题解
这道题还是一道模板题 里面涉及单点的更新和区间的求和。代码还是易于理解,每次更新完后记得更新父节点就好了。
#include<iostream> #include<cmath> #include<cstring> #include<vector> #include<stdlib.h> #include<stdio.h> #include<algorithm> #include<map> #include <set> #include <list> #include <deque> #include<sstream> #include<time.h> #define pi 3.1415926 #define N 2005 #define M 15 #define INF 0x6f6f6f6f #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 using namespace std; typedef long long ll; const int maxn = 55555; const int day =21252; const int mod=1000000007; int sum[maxn<<2];//要开4倍的节点 void pushup(int rt)//更新父节点 { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void build(int l,int r,int rt)//建树 { if(r==l) { scanf("%d",&sum[rt]); return ; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } void updata(int p,int add,int l,int r,int rt)//更新单点 { if(l==r) { sum[rt]+=add; return ; } int m=(l+r)>>1; if(p<=m) updata(p,add,lson); else updata(p,add,rson); pushup(rt); } 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; int ret=0; if(L<=m) ret+=query(L,R,lson); if(R>m) ret+=query(L,R,rson); return ret; } int main() { int t,n; scanf("%d",&t); for (int cas = 1 ; cas <= t ; cas ++) { scanf("%d",&n); build(1 , n , 1); printf("Case %d:\n",cas); char op[10]; while (scanf("%s",op)) { if (op[0] == 'E') break; int a , b; scanf("%d %d",&a,&b); if (op[0] == 'Q') printf("%d\n",query(a , b , 1 , n ,1)); else if (op[0] == 'S') updata(a , -b , 1 , n , 1); else updata(a , b , 1 , n , 1); } } return 0; }