关于线段树基础
发布日期:2021-11-02 09:49:08
浏览次数:1
分类:技术文章
本文共 4364 字,大约阅读时间需要 14 分钟。
线段树(c++)
需求:
必须:二分法,树的基础
拓展:补码,反码,移码,lowbit()建议先看看这个:
https://blog.csdn.net/zearot/article/details/52280189
了解什么是线段树及用途线段树,类模板题
Just a Hook http://acm.hdu.edu.cn/showproblem.php?pid=1698#include#include #include #include #include using namespace std;const int t=100009;struct node{ int v,l,r,mid;}tree[t<<2]; void pushdown(int rt){ tree[rt<<1].v=tree[rt<<1|1].v=tree[rt].v; tree[rt].v=-1;}void build(int l,int r,int rt){ tree[rt].l=l; tree[rt].r=r; tree[rt].v=1; tree[rt].mid=(l+r)>>1; if(l==r) { return; } build(l,tree[rt].mid,rt<<1); build(tree[rt].mid+1,r,rt<<1|1);}void add(int l,int r,int v,int rt){ if(tree[rt].l>=l&&tree[rt].r<=r) { tree[rt].v=v; return; } if(tree[rt].v!=-1) pushdown(rt); if(r<=tree[rt].mid) { add(l,r,v,rt<<1); }else if(l>tree[rt].mid){ add(l,r,v,rt<<1|1); }else{ add(l,tree[rt].mid,v,rt<<1); add(tree[rt].mid+1,r,v,rt<<1|1); }}int find(int rt){ if(tree[rt].v!=-1) return tree[rt].v*(tree[rt].r-tree[rt].l+1); else return find(rt<<1)+find(rt<<1|1);}int main() { int N,n,m,i,j,k,v,c=0; cin>>N; while(N--) { scanf("%d %d",&n,&m); build(1,n,1); for(i=1;i<=m;i++) { scanf("%d%d%d",&j,&k,&v); add(j,k,v,1); } printf("Case %d: The total value of the hook is %d.\n",++c,find(1)); } return 0;}
拓展:
其中用到了lowbit()函数,相比其余方法的代码可以说是精简了不少,但要明白其中的原理,还需掌握补码,反码,移码等相关知识。
#include#include #include #include #include #include using namespace std;int c[50100];int lowbit(int t){ return t&(-t);}int getSum(int n){ int sum=0; while(n>0) { sum+=c[n]; n-=lowbit(n); } return sum;}void change(int i,int v,int n){ while(i<=n) { c[i]+=v; i+=lowbit(i); }}int main(){ int T; cin>>T; int num=1; while(T--) { memset(c,0,sizeof(c)); cout<<"Case "< <<":\n"; int N,a; cin>>N; for(int i=1;i<=N;i++) { scanf("%d",&a); change(i,a,N); } char cmd[10]; while(scanf("%s",cmd),cmd[0]!='E') { int p,q; if(cmd[0]=='A') { scanf("%d%d",&p,&q); change(p,q,N); }else if(cmd[0]=='S'){ scanf("%d%d",&p,&q); change(p,-q,N); }else{ scanf("%d%d",&p,&q); if(p!=1) printf("%d\n",getSum(q)-getSum(p-1)); else printf("%d\n",getSum(q)); } } } return 0;}
正常做法
#include#include using namespace std;const int maxn = 5e4 + 10;int ans;struct node { int left, right, sum;} tree[maxn * 4];void build(int left, int right, int rt) { tree[rt].left = left; tree[rt].right = right; if (left == right) { scanf("%d", &tree[rt].sum); return; } int mid = (tree[rt].left + tree[rt].right) / 2; build(left, mid, rt * 2); build(mid + 1, right, rt * 2 + 1); tree[rt].sum = tree[rt * 2].sum + tree[rt * 2 + 1].sum;}void update(int left, int right, int rt, int pos, int add) { if (left == right) { tree[rt].sum += add; return; } int mid = (tree[rt].left + tree[rt].right) / 2; if (pos <= mid) { update(left, mid, rt * 2, pos, add); } else { update(mid + 1, right, rt * 2 + 1, pos, add); } tree[rt].sum = tree[rt * 2].sum + tree[rt * 2 + 1].sum;}void query(int left, int right, int rt, int L, int R) { if (L <= left && right <= R) { ans = ans + tree[rt].sum; return; } int mid = (tree[rt].left + tree[rt].right) / 2; if (R <= mid) { query(left, mid, rt * 2, L, R); } else if (L > mid) { query(mid + 1, right, rt * 2 + 1, L, R); } else { query(left, mid, rt * 2, L, R); query(mid + 1, right, rt * 2 + 1, L, R); }}int main() { int t, n, cnt, a, b; char str[10]; cnt = 1; cin >> t; while (t--) { cin >> n; build(1, n, 1); printf("Case %d:\n", cnt++); while (cin >> str) { if (str[0] == 'E') { break; } cin >> a >> b; if (str[0] == 'Q') { ans = 0; query(1, n, 1, a, b); printf("%d\n", ans); } else if (str[0] == 'A') { update(1, n, 1, a, b); } else if (str[0] == 'S') { update(1, n, 1, a, -b); } } } return 0;}
最后
线段树还有更多的用法,比如区间修改,扫描线,非递归写法等,详见这篇文章: https://blog.csdn.net/zearot/article/details/48299459转载地址:https://blog.csdn.net/weixin_43820352/article/details/88969542 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
逛到本站,mark一下
[***.202.152.39]2024年04月24日 14时51分10秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
D*算法
2019-04-30
强化学习(四) —— Actor-Critic演员评论家 & code
2019-04-30
RESTful API
2019-04-30
优化算法(四)——粒子群优化算法(PSO)
2019-04-30
数据在Oracle中的存储
2019-04-30
轨迹规划 trajectory planning
2019-04-30
AGV自动导引运输车
2019-04-30
Trie树(字典树)
2019-04-30
COMP7404 Machine Learing——KNN
2019-04-30
COMP7404 Machine Learing——SVM
2019-04-30
COMP7404 Machine Learing——ROC
2019-04-30
Python量子计算qiskit
2019-04-30
Python的多线程不是真的多线程(GIL全局解释器锁)
2019-04-30