2020年初一初二集训队(线段树) 基本操作
有N个整数,对这N个整数构造一颗线段树,每个结点用一个sum保留所代表区间的和。
建树后按照后续遍历,输出各个结点的sum。
输入格式
第一行,一个整数N。 1 <= N <= 100000。
第二行,N整数。每个整数范围[1,10^6]。
输出格式
一行, 若干个整数。
输入/输出例子1
输入:
5
3 6 8 2 9
输出:
3 6 9 8 17 2 9 11 28
样例解释
根结点1号结点,区间范围是[1,5]共5个结点,递归根结点的左子树,递归根结点的右子树。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #include <bits/stdc++.h> using namespace std; const int N=100005; struct treeNode { int l, r; long long sum; }tree[N<<2]; int n; long long a[N]; void build_stree( int cur, int l, int r) { tree[cur].l=l, tree[cur].r=r; if (l==r) { tree[cur].sum=a[l]; return ; } int mid=l+r>>1, ls=cur*2, rs=cur*2+1; build_stree(ls, l, mid); build_stree(rs, mid+1, r); tree[cur].sum=tree[ls].sum+tree[rs].sum; } void dfs( int cur, int l, int r) { if (l==r) { printf ( "%lld " , tree[cur].sum); return ; } int mid=tree[cur].l+tree[cur].r>>1, ls=cur*2, rs=cur*2+1; dfs(ls, l, mid); dfs(rs, mid+1, r); printf ( "%lld " , tree[cur].sum); } int main() { scanf ( "%d" , &n); for ( int i=1; i<=n; i++) scanf ( "%lld" , &a[i]); build_stree(1, 1, n); dfs(1, 1, n); return 0; } |
有N个整数,对这N个整数构造一颗线段树,每个结点用一个sum保留所代表区间的和。
有Q个询问,第i个询问给出s[i]和t[i],表示询问第s[i]个数至第t[i]个数的总和。
输入格式
第一行,N和Q。 1 <= N, Q <= 100000。
第二行,N个整数,每个整数范围[1,10^6]。
接下来有Q行,第i行是s[i]和t[i]。
输出格式
共Q行,每行一个整数。
输入/输出例子1
输入:
5 2
3 6 8 2 9
2 4
3 5
输出:
16
19
样例解释
本题纯粹是为了入门,请不要用部分和做。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #include <bits/stdc++.h> using namespace std; typedef long long LL; const int N=100100; struct treeNode { int l, r; LL sum; }tree[N<<2]; int n, q, x, y; LL a[N]; void build_stree( int cur, int l, int r) { tree[cur].l=l, tree[cur].r=r; if (l==r) { tree[cur].sum=a[l]; return ; } int mid=l+r>>1, ls=cur*2, rs=cur*2+1; build_stree(ls, l, mid); build_stree(rs, mid+1, r); tree[cur].sum=tree[ls].sum+tree[rs].sum; } LL query( int cur, int l, int r) { if (l<=tree[cur].l && tree[cur].r<=r) return tree[cur].sum; int mid=tree[cur].l+tree[cur].r>>1, ls=cur*2, rs=cur*2+1; LL sum1=0, sum2=0; if (l<=mid) sum1=query(ls, l, r); if (r>=mid+1) sum2=query(rs, l, r); return sum1+sum2; } int main() { scanf ( "%d%d" , &n, &q); for ( int i=1; i<=n; i++) scanf ( "%lld" , &a[i]); build_stree(1, 1, n); while (q--) { scanf ( "%d%d" , &x, &y); if (x>y) swap(x, y); printf ( "%lld\n" , query(1, x, y)); } return 0; } |
在N(1<=N<=100000)个数A1…An组成的序列上进行M(1<=M<=100000)次操作,操作有两种:
1 x y:表示修改A[x]为y;
2 x y:询问x到y之间的最大值。
输入格式
第一行输入N(1 <= N <= 100000),表示序列的长度,接下来N行输入原始序列;
接下来一行输入M(1 <= M <= 100000)表示操作的次数,接下来M行,每行为1 x y或2 x y
输出格式
对于每个操作(2)输出对应的答案。
输入/输出例子1
输入:
5
1
2
3
4
5
3
2 1 4
1 3 5
2 2 4
输出:
4
5
样例解释
【限制】
保证序列中的所有的数都在int范围内
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | #include <bits/stdc++.h> using namespace std; typedef long long LL; const int N=100100; struct treeNode { int l, r; LL mx; }tree[4*N]; int n, q, w, x, y; LL a[N]; void build_stree( int cur, int l, int r) { tree[cur].l=l, tree[cur].r=r; if (l==r) { tree[cur].mx=a[l]; return ; } int mid=l+r>>1, ls=cur*2, rs=cur*2+1; build_stree(ls, l, mid); build_stree(rs, mid+1, r); tree[cur].mx=max(tree[ls].mx, tree[rs].mx); } LL query( int cur, int l, int r) { if (l<=tree[cur].l && tree[cur].r<=r) return tree[cur].mx; int mid=tree[cur].l+tree[cur].r>>1, ls=cur*2, rs=cur*2+1; LL mx1=0, mx2=0; if (l<=mid) mx1=query(ls, l, r); if (r>=mid+1) mx2=query(rs, l, r); return max(mx1, mx2); } void point_update( int cur, int pos, int val) { if (tree[cur].l==tree[cur].r && tree[cur].l==pos) { tree[cur].mx=val; return ; } int mid=tree[cur].l+tree[cur].r>>1, ls=2*cur, rs=2*cur+1; if (pos<=mid) point_update(ls, pos, val); else if (pos>=mid+1) point_update(rs, pos, val); tree[cur].mx=max(tree[ls].mx, tree[rs].mx); } int main() { scanf ( "%d" , &n); for ( int i=1; i<=n; i++) scanf ( "%lld" , &a[i]); scanf ( "%d" , &q); build_stree(1, 1, n); while (q--) { scanf ( "%d%d%d" , &w, &x, &y); //if (x>y) swap(x, y); if (w==1) point_update(1, x, y); else if (w==2) printf ( "%lld\n" , query(1, x, y)); } return 0; } |
在N(1 <= N <= 100000)个数A1…An组成的序列上进行M(1 <= M <= 100000)次操作,操作有两种:
1 L R C:表示把A[L]到A[R]增加C(C的绝对值不超过10000);
2 L R:询问A[L]到A[R]之间的最大值。
输入格式
第一行输入N(1 <= N <= 100000),表示序列的长度,接下来N行输入原始序列;
接下来一行输入M(1 <= M <= 100000)表示操作的次数,接下来M行,每行为1 L R C或2 L R
输出格式
对于每个操作(2)输出对应的答案。
输入/输出例子1
输入:
5
1
2
3
4
5
3
2 1 4
1 1 3 3
2 3 5
输出:
4
6
样例解释
【限制】
保证序列中的所有的数都在int范围内
在N(1 <= N <= 100000)个数A1…An组成的序列上进行M(1 <= M <= 100000)次操作,操作有两种:
1 L R C:表示把A[L]到A[R]增加C(C的绝对值不超过10000);
2 L R:询问A[L]到A[R]之间的总和。
输入格式
第一行输入N(1 <= N <= 100000),表示序列的长度,接下来N行输入原始序列;
接下来一行输入M(1 <= M <= 100000)表示操作的次数,接下来M行,每行为1 L R C或2 L R
输出格式
对于每个操作(2)输出对应的答案。
输入/输出例子1
输入:
5
1
2
3
4
5
3
2 1 4
1 1 3 3
2 3 5
输出:
10
15
样例解释
无
暂无
__EOF__

本文链接:https://www.cnblogs.com/didiao233/p/17892733.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」