【模板】 线段树(部分功能)
嗯...
这个模板里有线段树的建树、标记下放、单点查询、单点加、区间和、单点更改。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 struct Tree{ 2 int l,r,f = 0; 3 long long wi; 4 }tree[Maxn*3]; 5 6 void build(int le,int ri,int k){ 7 tree[k].l = le; 8 tree[k].r = ri; 9 if(le == ri){ 10 scanf("%lld",&tree[k].wi); 11 return; 12 } 13 int m = (le + ri)/2; 14 build(le,m,k*2); 15 build(m+1,ri,k*2+1); 16 tree[k].wi = tree[k*2].wi + tree[k*2+1].wi; 17 }//建树 18 19 void down(int k){ 20 tree[k*2].f += tree[k].f; 21 tree[k*2+1].f += tree[k].f; 22 tree[k*2].wi += tree[k].f*(tree[k*2].r + 1 - tree[k*2].l); 23 tree[k*2+1].wi += tree[k].f*(tree[k*2+1].r + 1 - tree[k*2+1].l); 24 tree[k].f = 0; 25 }//标记下放 26 27 void ask(int k){ 28 if(tree[k].l == tree[k].r){ 29 ans = tree[k].wi; 30 return; 31 } 32 if(tree[k].f)down(k); 33 int m = (tree[k].l + tree[k].r)/2; 34 if(x <= m)ask(k*2); 35 else ask(k*2+1); 36 }//单点查询 37 38 void add(int k){ 39 if(tree[k].l == tree[k].r){ 40 tree[k].wi += y; 41 return; 42 } 43 if(tree[k].f)down(k); 44 int m = (tree[k].l + tree[k].r)/2; 45 if(x <= m)add(k*2); 46 else add(k*2+1); 47 tree[k].wi = tree[k*2].wi + tree[k*2+1].wi; 48 }//单点加 49 50 void sum(int k){ 51 if(x <= tree[k].l && tree[k].r <= y){ 52 ans += tree[k].wi; 53 return; 54 } 55 if(tree[k].f)down(k); 56 int m = (tree[k].l+tree[k].r)/2; 57 if(x <= m)sum(k*2); 58 if(y > m)sum(k*2+1); 59 }//区间和 60 61 void change(int k){ 62 if(x <= tree[k].l && tree[k].r <= y){ 63 tree[k].f+=z; 64 tree[k].wi += z*(tree[k].r + 1 - tree[k].l); 65 return; 66 } 67 if(tree[k].f)down(k); 68 int m = (tree[k].l + tree[k].r)/2; 69 if(x <= m)change(k*2); 70 if(m < y)change(k*2+1); 71 tree[k].wi = tree[k*2].wi + tree[k*2+1].wi; 72 }//单点修改