[模板]线段树1

https://www.luogu.org/problemnew/show/P3372

 1 #include <bits/stdc++.h>
 2 #define lowbit(a) (a&-a)
 3
 4 using namespace std;
 5 typedef long long LL;
 6
 7 const LL N = 100010;
 8 LL n, m, q, c[N], c2[N], opt, x, y, k;
 9 inline LL Sum(LL *a, LL x){
10     LL ans = 0;
11     for(LL i = x; i; i -= lowbit(i)) ans += a[i];
12     return ans;
13 }
14
15 inline void add(LL *a, LL x, LL q){
16     for(LL i = x; i <= n; i += lowbit(i)) a[i] += q;
17 }
18
19 inline void read(LL &x){
20     register LL c = getchar(), f = 1;x = 0;
21     while(!isdigit(c)) {if (c == ‘-‘) f = -1; c = getchar();}
22     while(isdigit(c)) x = (x<<3)+(x<<1)+(c^48), c = getchar();
23     x *= f;
24 }
25
26 int main(void){
27     LL now, tmp = 0;
28     read(n); read(m);
29     for(register LL i = 1; i <= n; ++i){
30         read(now);
31         add(c, i, now-tmp);
32         add(c2, i, (i-1)*(now-tmp));
33         tmp = now;
34     }
35     while(m--){
36         LL opt; read(opt);
37         if (opt == 1){
38             read(x), read(y), read(k);
39             add(c, x, k), add(c, y+1, -k), add(c2, x, (x-1)*k), add(c2, y+1, -k*y);
40         }
41         else {
42             read(x), read(y);
43             LL sum1 = (x-1)*Sum(c,x-1)-Sum(c2,x-1),
44                  sum2 = y*Sum(c,y)-Sum(c2,y);
45             printf("%lld\n", sum2-sum1);
46         }
47     }
48     return 0;
49 }

树状数组

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #define lson (o<<1)
 7 #define rson (o<<1|1)
 8 #define midd int mid = (l+r)>>1
 9 using namespace std;
10 const int N = 100010;
11
12 int a[N], n, m;
13
14 inline int read() {
15     register int n, ch;
16     n = 0, ch = getchar();
17     while (!isdigit(ch)) ch = getchar();
18     while (isdigit(ch)) n = (n << 3) + (n << 1) + ch - ‘0‘, ch = getchar();
19     return n;
20 }
21 struct Node{
22     long long sum, add;
23 }t[N<<2];
24 inline void pushup(int o){t[o].sum=t[lson].sum+t[rson].sum;}
25 inline void pushdown(int o, int l, int r){
26     int ls = lson, rs = rson, mid = (l+r)>>1;
27   t[ls].add+=t[o].add;
28   t[rs].add+=t[o].add;
29   t[ls].sum+=(mid-l+1)*t[o].add;
30   t[rs].sum+=(r-mid)*t[o].add;
31   t[o].add=0;
32 }
33 inline void secadd(int o,int l, int r, int ql, int qr, int v){
34     if (ql<=l&&r<=qr){
35         t[o].add+=v;
36         t[o].sum+=(r-l+1)*v;
37         return ;
38     }
39     int mid = (l+r)>>1;
40       if (t[o].add) pushdown(o, l, r);
41       if (ql<=mid) secadd(lson,l,mid,ql,qr,v);
42         if (qr>mid) secadd(rson,mid+1,r,ql,qr,v);
43     pushup(o);
44 }
45 inline long long query(int o,int l, int r, int ql, int qr){
46     if (ql<=l&&r<=qr)
47         return t[o].sum;
48     if (t[o].add) pushdown(o,l,r);int mid = (l+r)>>1;long long ans = 0;
49     if (ql<=mid) ans+=query(lson,l,mid,ql,qr);
50         if (qr>mid) ans += query(rson,mid+1,r,ql,qr);
51         return ans;
52 }
53 inline void build(int o, int l, int r){
54     if (l==r){t[o].sum=a[l];return ;}
55     int mid = (l+r)>>1;
56     build(lson,l,mid), build(rson,mid+1,r);
57     pushup(o);
58 }
59
60 int main(void){
61     n=read(), m=read();
62     for(register int i = 1; i <= n; ++i){
63         a[i] = read();
64     }
65     build(1,1,n);
66     while(m--){
67         register int bs = read(), x = read(), y = read(), k;
68         if (bs == 1){k = read(); secadd(1,1,n,x,y,k);}
69         else printf("%lld\n", query(1,1,n,x,y));
70     }
71     return 0;
72 }

线段树

原文地址:https://www.cnblogs.com/Ycrpro/p/8452481.html

时间: 2024-10-12 16:23:30

[模板]线段树1的相关文章

算法模板——线段树1(区间加法+区间求和)

实现功能——1:区间加法:2:区间求和 最基础最经典的线段树模板.由于这里面操作无顺序之分,所以不需要向下pushup,直接累积即可 1 var 2 i,j,k,l,m,n,a1,a2,a3,a4:longint; 3 a,b:array[0..100000] of longint; 4 function max(x,y:longint):longint;inline; 5 begin 6 if x>y then max:=x else max:=y; 7 end; 8 function min

算法模板——线段树5(区间开根+区间求和)

实现功能——1:区间开根:2:区间求和(此模板以BZOJ3038为例) 作为一个非常规的线段树操作,其tag也比较特殊呵呵哒 1 var 2 i,j,k,l,m,n:longint; 3 a,b:array[0..500000] of int64; 4 function max(x,y:longint):longint;inline; 5 begin 6 if x>y then max:=x else max:=y; 7 end; 8 function min(x,y:longint):long

【线段树】【P3372】模板-线段树

百度百科 Definition&Solution 线段树是一种log级别的树形结构,可以处理区间修改以及区间查询问题.期望情况下,复杂度为O(nlogn). 核心思想见百度百科,线段树即将每个线段分成左右两个线段做左右子树.一个线段没有子树,当且仅当线段表示的区间为[a,a]. 由于编号为k的节点的子节点为2k以及2k+1,线段树可以快速的递归左右叶节点. lazy标记:当进行区间修改的时候,如果一个区间整体全部被包含于要修改的区间,则可以将该区间的值修改后,将lazy标记打在区间上,不再递归左

CSU-ACM集训-模板-线段树进阶

A题 原CF 438D The Child and Sequence 题意 给一串数字,m次操作,1.区间查询:2.区间取模:3.单点修改 基本思路 考虑到模如果大于区间的最大值,则取模没有意义.若小于则向下查询并修改,考虑到一个数每次取模最多为原数的\(1/2\),则可认为修改次数不超过\(\log{2}{n}\) 时间复杂度为\(O(n\log{2}{n}\log{2}{n})\) #include<bits/stdc++.h> #define FOR(i,a,b) for(int i=a

模板 - 线段树

线段树还需要模板的菜鸡 #include<bits/stdc++.h> using namespace std; typedef long long ll; #define lt ls, l, m #define rt rs, m + 1, r #define ls (o<<1) #define rs (o<<1|1) const int MAXM = 100000 + 5; ll a[MAXM]; ll st[MAXM * 4], lazy[MAXM * 4]; in

算法模板——线段树4(区间加+区间乘+区间覆盖值+区间求和)

实现功能——1:区间加法 2:区间乘法 3:区间覆盖值 4:区间求和 这是个四种常见线段树功能的集合版哦...么么哒(其实只要协调好三种tag的关系并不算太难——前提是想明白了线段树的工作模式) 代码长度几经修改后也大为缩水 还有!!!——通过BZOJ1798反复的尝试,我的出来一个重要结论——尽量减少pushup操作的不必要使用次数,对于程序提速有明显的效果!!! 1 type vet=record 2 a0,a1:longint; 3 end; 4 var 5 i,j,k,l,m,n,a1,

算法模板——线段树7(骰子翻转问题)

实现功能:首先输入一个长度为N的序列,由1-4组成(1表示向前滚一下,2表示向后滚一下,3表示向左滚一下,4表示向右滚一下,骰子原始状态:上1前2左4右5后3下6),然后输入任意多个操作,输入“1 x y”表示将序列第x个数改成y,输入“2 x y”表示输出对于原始状态的骰子,按照从x到y的序列操作可以使骰子变成什么样子 原理:还是线段树,而且只需要点修改区间访问,不过这里面区间之间的合并不再是简单的累加了,而是——置换关系,通过置换关系的合并实现及时的维护即可 1 type 2 cube=ar

模板——线段树

一颗最简单的线段树orz...但是感觉还是拍得好麻烦... 只支持区间加和区间查询 #include<iostream> #include<cstdlib> #include<cstdio> #include<algorithm> using namespace std; int a[2000010],n,m; typedef long long ll; struct inlinetree{ int l,r; ll s,lazy; }lt[34000100]

模板 线段树的区间修改

线段树的区间修改 区间绝对标记 改成同一个数 注意打标记前 要先判断 是否有标记 这道题不能像加法标记一样 标记初始化为 0 如果这道题 可以将数变成 0 那么0 就不能为初始值了 然后我们初始值要选择一个不会被干扰到的数字 比如 -1 就不会变成 -1 另外还要注意在标记清空时 要将标记 变成 -1 而不是 0 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstr

算法模板——线段树之Lazy标记

一.前言 前面我们已经知道线段树能够进行单点修改和区间查询操作(基本线段树).那么如果需要修改的是一个区间该怎么办呢?如果是暴力修改到叶子节点,复杂度即为\(O(nlog_n)\),显然是十分不优秀的.那么我们能不能向区间查询一样把复杂度降到\(O(log_n)\)呢? 二.算法流程 线段树肯定是兹瓷\(O(log_n)\)修改的,否则发明它有何用处?所以,我我们现在需要知道,如何快速进行区间修改操作.首先,我们回顾下终止节点 假定我要在这个图上修改区间[2,8],我只要修改掉图上所有的终止节点