逐步向下递归,找到数组内的结点。输入进叶子结点中,然后返回上一个调用的区间(去更新)
去更新这个区间, 这里主要用到的是线段树。小伙伴想了解具体的方法,可以去看看线段树的内容,谈谈我的想法吧,线段树,其实就是算是二叉排序树的一种(但也不像)因为二叉排序树,并不要求是二叉完全树,而线段树是二叉完全树,并要求以二叉排序树的方法进行,查找,更改。
最后一步一步区间进行分配,最后叶子结点都是数组的结点。非叶子都是a[i]到a[j]的区间。所以有了左边界与有边界的说法。
线段树,等等有时间的时候再细谈,
但毕竟写题是为了提升,所以希望,各位不要只在意题,要去了解,题目里所涉及到的内容。
#include <iostream> using namespace std; struct linetree { int l=0;//左边界 int r=0;//右边界 long long sum=0;//左右子树的和 int max=0;//左右子树的最大值(也可以叫区间内的最大值) }; linetree a[500000]; void upnode (int k) { a[k].max=a[2*k+1].max>a[2*k].max?a[2*k+1].max:a[2*k].max; a[k].sum=a[2*k+1].sum+a[2*k].sum; } int creat(int n[],int fakel,int faker,int k) { if(fakel==faker) { a[k].l=fakel; a[k].r=faker; a[k].sum=n[fakel]; a[k].max=n[fakel]; return 0; } else { a[k].l=fakel; a[k].r=faker; int middle=(fakel+faker)/2; creat(n,fakel,middle,2*k); creat(n,middle+1,faker,2*k+1); upnode(k); } } void change(int x,int y,int k) { if(a[k].l==a[k].r&&a[k].l==x) { a[k].sum=y; a[k].max=y; } else { int middle; middle=(a[k].l+a[k].r)/2; if(x<=middle) { change(x,y,2*k); } else { change(x,y,2*k+1); } upnode(k); } } int getsum(int x,int y,int k) { if(a[k].l==x&&a[k].r==y) { return a[k].sum; } else { int middle; middle=(a[k].l+a[k].r)/2; if(y<=middle) { return getsum(x,y,2*k); } else if(x<=middle&&y>middle) { return getsum(x,middle,2*k)+getsum(middle+1,y,2*k+1); } else { return getsum(x,y,2*k+1); } } } int getmax(int x,int y,int k) { if(a[k].l==x&&a[k].r==y) { return a[k].max; } else { int middle; middle=(a[k].l+a[k].r)/2; if(y<=middle) { return getmax(x,y,2*k); } else if(x<=middle&&y>middle) { return getmax(x,middle,2*k)>getmax(middle+1,y,2*k+1)?getmax(x,middle,2*k):getmax(middle+1,y,2*k+1); } else { return getmax(x,y,2*k+1); } } } int main() { int m,n; cin>>n>>m; int b[n+1]; for(int i=1;i<=n;i++) { cin>>b[i]; } creat(b,1,n,1); int x,y; for(int i=1;i<=m;i++) { int loop; cin>>loop; if(loop==1) { cin>>x>>y; change(x,y,1); } if(loop==2) { cin>>x>>y; cout<<getsum(x,y,1)<<endl; } if(loop==3) { cin>>x>>y; cout<<getmax(x,y,1)<<endl; } } return 0; }