线段树,求和,最值,数据更新

来源:互联网 发布:日本网络电视jitakutv 编辑:程序博客网 时间:2024/05/23 13:59

位运算要比加减预算速度快

#include<stdio.h>#include<algorithm>using namespace std;struct Node{int l,r,sum,Max,Min;}Tree[1000<<2];//开的空间至少要4倍.左移两位就是4倍void PushUp(int o){Tree[o].sum=Tree[o*2].sum+Tree[o*2+1].sum; Tree[o].Max=max(Tree[o*2].Max,Tree[o*2+1].Max);Tree[o].Min=min(Tree[o*2].Min,Tree[o*2+1].Min);}void BuidTree(int o,int l,int r)//建树 {Tree[o].l=l;Tree[o].r=r;if(l==r)//搜索到底层,输入数据 {int t;scanf("%d",&t);Tree[o].Max=Tree[o].Min=Tree[o].sum=t;return;}int mid=(l+r)>>1;BuidTree(o*2,l,mid);//递归找左子树BuidTree(o*2+1,mid+1,r);//递归找右子树 PushUp(o);}void UpDate(int o,int l,int r,int x,int y)//数据更新,将底层x节点值变为y {if(l==r){Tree[o].Max=Tree[o].Min=Tree[o].sum=y;return ; }int mid=(l+r)>>1;if(x<=mid)UpDate(o*2,l,mid,x,y);elseUpDate(o*2+1,mid+1,r,x,y);PushUp(o);}int QuerySum(int o,int l,int r,int x,int y)//x到y的和 {if(l==x&&y==r)return Tree[o].sum;int mid=(l+r)>>1;if(mid<x)return QuerySum(o*2+1,mid+1,r,x,y);else if(y<=mid)return QuerySum(o*2,l,mid,x,y);elsereturn QuerySum(o*2,l,mid,x,mid)+QuerySum(o*2+1,mid+1,r,mid+1,y);}int QueryMax(int o,int l,int r,int x,int y)//x到y最大 {if(l==x&&y==r)return Tree[o].Max;int mid=(l+r)>>1;if(mid<x)return QueryMax(o*2+1,mid+1,r,x,y);else if(y<=mid)return QueryMax(o*2,l,mid,x,y);elsereturn max(QueryMax(o*2,l,mid,x,mid),QueryMax(o*2+1,mid+1,r,mid+1,y));}int QueryMin(int o,int l,int r,int x,int y)//x到y最小 {if(l==x&&y==r)return Tree[o].Min;int mid=(l+r)>>1;if(mid<x)return QueryMin(o*2+1,mid+1,r,x,y);else if(y<=mid)return QueryMin(o*2,l,mid,x,y);elsereturn min(QueryMin(o*2,l,mid,x,mid),QueryMin(o*2+1,mid+1,r,mid+1,y));}int main(){int n,T,st,endd;scanf("%d",&T);//T组数据 while(T--){scanf("%d",&n);//n个数 scanf("%d%d",&st,&endd);//查询的起止点 BuidTree(1,1,n);printf("%d\n",QuerySum(1,1,n,st,endd));printf("%d\n",QueryMax(1,1,n,st,endd));printf("%d\n",QueryMin(1,1,n,st,endd));}return 0;}