初识 线段树
线段树
作为一个刚接触线段树不久的OI新手,我认为线段树一般是区间或单点的查询或修改
下面粘一些本蒟蒻的板子代码:
洛谷:
#include<algorithm> #include<cstdio> #define N 200001 using namespace std; int n, m, a, t; struct nond { int ll, rr; long long sum, flag; }tree[4*N]; void tree_up(int now) { tree[now].sum = tree[now*2].sum+tree[now*2+1].sum; } void tree_down(int now) { tree[now*2].flag += tree[now].flag; tree[now*2+1].flag += tree[now].flag; tree[now*2].sum += (tree[now*2].rr-tree[now*2].ll+1) * tree[now].flag; tree[now*2+1].sum += (tree[now*2+1].rr-tree[now*2+1].ll+1) * tree[now].flag; tree[now].flag = 0; return ; } void tree_build(int now, int l, int r) { tree[now].ll = l; tree[now].rr = r; if(l == r) { scanf("%d", &tree[now].sum); return ; } int mid = (l+r) / 2; tree_build(now*2, l, mid); tree_build(now*2+1, mid+1, r); tree_up(now); } void tree_change(int now, int l, int r) { if(tree[now].ll==l && tree[now].rr==r) { tree[now].sum += (tree[now].rr-tree[now].ll+1) * t; tree[now].flag += t; return ; } if(tree[now].flag) tree_down(now); int mid = (tree[now].ll+tree[now].rr) / 2; if(l<=mid && mid<r) tree_change(now*2, l, mid), tree_change(now*2+1, mid+1, r); else if(r<=mid) tree_change(now*2, l, r); else tree_change(now*2+1, l, r); tree_up(now); } long long tree_query(int now, int l, int r) { if(tree[now].ll==l && tree[now].rr==r) return tree[now].sum; if(tree[now].flag) tree_down(now); int mid = (tree[now].ll+tree[now].rr) / 2; if(l<=mid && mid<r) return tree_query(now*2, l, mid)+tree_query(now*2+1, mid+1, r); else if(r<=mid) return tree_query(now*2, l, r); else return tree_query(now*2+1, l, r); } int main() { scanf("%d%d", &n, &m); tree_build(1, 1, n); for(int i = 1; i <= m; i++) { scanf("%d", &a); if(a == 1) { int b, c; scanf("%d%d%d", &b, &c, &t); tree_change(1, b, c); } else { int b, c; scanf("%d%d", &b, &c); printf("%lld\n", tree_query(1, b, c)); } } return 0; }
#include<cstdio> #define LL long long #define N 100001 using namespace std; int n, m, p, x, y, z, k; int ll[4*N], rr[4*N]; LL flag1[4*N], flag2[4*N], sum[4*N]; void up(int now) { sum[now] = (sum[now*2] + sum[now*2+1]) % p; } void down(int now) { if(flag1[now]!=1) { flag1[now*2] = flag1[now*2] * flag1[now] % p; flag2[now*2] = flag2[now*2] * flag1[now] % p; flag1[now*2+1] = flag1[now*2+1] * flag1[now] % p; flag2[now*2+1] = flag2[now*2+1] * flag1[now] % p; sum[now*2] = sum[now*2] * flag1[now] % p; sum[now*2+1] = sum[now*2+1] * flag1[now] % p; flag1[now] = 1; } if(flag2[now]) { flag2[now*2] = (flag2[now*2] + flag2[now]) % p; flag2[now*2+1] = (flag2[now*2+1] + flag2[now]) % p; sum[now*2] = (sum[now*2] + (rr[now*2]-ll[now*2]+1)*flag2[now]%p) % p; sum[now*2+1] = (sum[now*2+1] + (rr[now*2+1]-ll[now*2+1]+1)*flag2[now]%p) % p; flag2[now] = 0; } return ; } void build(int now, int l, int r) { ll[now] = l; rr[now] = r; flag1[now] = 1; if(l == r) { scanf("%lld", &sum[now]); return ; } int mid = (l+r) / 2; build(now*2, l, mid); build(now*2+1, mid+1, r); up(now); } void change1(int now, int l, int r) { if(ll[now]==l && rr[now]==r) { flag1[now] = flag1[now] * z %p; flag2[now] = flag2[now] * z % p; sum[now] = sum[now] * z % p; return ; } if(flag2[now] || flag1[now]!=1) down(now); int mid = (ll[now]+rr[now]) / 2; if(l<=mid && mid<r) change1(now*2, l, mid), change1(now*2+1, mid+1, r); else if(r <= mid) change1(now*2, l, r); else change1(now*2+1, l, r); up(now); } void change2(int now, int l, int r) { if(ll[now]==l && rr[now]==r) { flag2[now] = (flag2[now] + z) % p; sum[now] = (sum[now] + (rr[now]-ll[now]+1)*z%p) % p; return ; } if(flag2[now] || flag1[now]!=1) down(now); int mid = (ll[now]+rr[now]) / 2; if(l<=mid && mid<r) change2(now*2, l, mid), change2(now*2+1, mid+1, r); else if(r <= mid) change2(now*2, l, r); else change2(now*2+1, l, r); up(now); } LL query(int now, int l, int r) { if(ll[now]==l && rr[now]==r) return sum[now]; if(flag2[now] || flag1[now]!=1) down(now); int mid = (ll[now]+rr[now]) / 2; if(l<=mid && mid<r) return(query(now*2, l, mid) % p + query(now*2+1, mid+1, r) % p) % p; else if(r <= mid) return query(now*2, l, r) % p; else return query(now*2+1, l, r) % p; } int main() { scanf("%d%d%d", &n, &m, &p); build(1, 1, n); for(int i = 1; i <= m; i++) { scanf("%d", &k); if(k == 1) {scanf("%d%d%d", &x, &y, &z); change1(1, x, y); } if(k == 2) {scanf("%d%d%d", &x, &y, &z); change2(1, x, y); } if(k == 3) {scanf("%d%d", &x, &y); printf("%lld\n", query(1, x, y) % p); } } return 0; }
codevs:
#include<algorithm> #include<cstring> #include<cstdio> #define N 100001 using namespace std; int n, m; int a, b, c; struct note { int ll, rr; int sum; }e[4*N]; void up(int now) { e[now].sum = e[now*2].sum + e[now*2+1].sum; } void build(int now, int l, int r) { e[now].ll = l; e[now].rr = r; if(l == r) { scanf("%d", &e[now].sum); return ; } int mid = (l+r) / 2; build(now*2, l, mid); build(now*2+1, mid+1, r); up(now); } void change(int now, int x, int y) { if(e[now].ll == e[now].rr) { e[now].sum += y; return ; } int mid = (e[now].ll+e[now].rr) / 2; if(x <= mid) change(now*2, x, y); else change(now*2+1, x, y); up(now); } int query(int now, int l, int r) { if(e[now].ll==l && e[now].rr==r) { return e[now].sum; } int mid = (e[now].ll+e[now].rr) / 2; if(l<=mid && mid<r) { return query(now*2, l, mid) + query(now*2+1, mid+1, r); } else if(r <= mid) return query(now*2, l, r); else return query(now*2+1, l, r); } int main() { scanf("%d", &n); build(1, 1, n); scanf("%d", &m); for(int i = 1; i <= m; i++) { scanf("%d%d%d", &a, &b, &c); if(a == 1) change(1, b, c); else printf("%d\n", query(1, b, c)); } return 0; }
#include<algorithm> #include<cstring> #include<cstdio> #define N 100001 using namespace std; int n, m, flag, t; struct note { int ll, rr; int sum, ok; }tree[4*N]; void tree_up(int now) { tree[now].sum = tree[now*2].sum + tree[now*2+1].sum; } void tree_down(int now) { tree[now*2].ok += tree[now].ok; tree[now*2+1].ok += tree[now].ok; tree[now*2].sum += (tree[now*2].rr-tree[now*2].ll+1) * tree[now].ok; tree[now*2+1].sum += (tree[now*2+1].rr-tree[now*2+1].ll+1) * tree[now].ok; tree[now].ok = 0; return ; } void tree_build(int now, int l, int r) { tree[now].ll = l; tree[now].rr = r; if(l == r) { scanf("%d", &tree[now].sum); return ; } int mid = (l+r) / 2; tree_build(now*2, l, mid); tree_build(now*2+1, mid+1, r); tree_up(now); } void tree_change(int now, int l, int r) { if(tree[now].ll==l && tree[now].rr==r) { tree[now].sum+=(tree[now].rr-tree[now].ll+1) * t; tree[now].ok += t; return ; } if(tree[now].ok) tree_down(now); int mid = (tree[now].ll+tree[now].rr) / 2; if(l<=mid && mid<r) tree_change(now*2, l, mid), tree_change(now*2+1, mid+1, r); else if(r <= mid) tree_change(now*2, l, r); else tree_change(now*2+1, l, r); tree_up(now); } int tree_query(int now, int l, int r) { if(tree[now].ll == tree[now].rr) { return tree[now].sum; } if(tree[now].ok) tree_down(now); int mid = (l+r) / 2; if(t <= mid) return tree_query(now*2, l, mid); else return tree_query(now*2+1, mid+1, r); } int main() { scanf("%d", &n); tree_build(1, 1, n); scanf("%d", &m); for(int i = 1; i <= m; i++) { scanf("%d", &flag); if(flag == 1) { int a, b; scanf("%d%d%d", &a, &b, &t); tree_change(1, a, b); } else { scanf("%d", &t); printf("%d\n", tree_query(1, 1, n)); } } return 0; }
#include<algorithm> #include<cstdio> #define N 200001 using namespace std; int n, m, a, t; struct nond { int ll, rr; long long sum, flag; }tree[4*N]; void tree_up(int now) { tree[now].sum = tree[now*2].sum+tree[now*2+1].sum; } void tree_down(int now) { tree[now*2].flag += tree[now].flag; tree[now*2+1].flag += tree[now].flag; tree[now*2].sum += (tree[now*2].rr-tree[now*2].ll+1) * tree[now].flag; tree[now*2+1].sum += (tree[now*2+1].rr-tree[now*2+1].ll+1) * tree[now].flag; tree[now].flag = 0; return ; } void tree_build(int now, int l, int r) { tree[now].ll = l; tree[now].rr = r; if(l == r) { scanf("%d", &tree[now].sum); return ; } int mid = (l+r) / 2; tree_build(now*2, l, mid); tree_build(now*2+1, mid+1, r); tree_up(now); } void tree_change(int now, int l, int r) { if(tree[now].ll==l && tree[now].rr==r) { tree[now].sum += (tree[now].rr-tree[now].ll+1) * t; tree[now].flag += t; return ; } if(tree[now].flag) tree_down(now); int mid = (tree[now].ll+tree[now].rr) / 2; if(l<=mid && mid<r) tree_change(now*2, l, mid), tree_change(now*2+1, mid+1, r); else if(r<=mid) tree_change(now*2, l, r); else tree_change(now*2+1, l, r); tree_up(now); } long long tree_query(int now, int l, int r) { if(tree[now].ll==l && tree[now].rr==r) return tree[now].sum; if(tree[now].flag) tree_down(now); int mid = (tree[now].ll+tree[now].rr) / 2; if(l<=mid && mid<r) return tree_query(now*2, l, mid)+tree_query(now*2+1, mid+1, r); else if(r<=mid) return tree_query(now*2, l, r); else return tree_query(now*2+1, l, r); } int main() { scanf("%d", &n); tree_build(1, 1, n); scanf("%d", &m); for(int i = 1; i <= m; i++) { scanf("%d", &a); if(a == 1) { int b, c; scanf("%d%d%d", &b, &c, &t); tree_change(1, b, c); } else { int b, c; scanf("%d%d", &b, &c); printf("%lld\n", tree_query(1, b, c)); } } return 0; }