对单个点的修改,和对一段区间的查询:
//线段树单个点修改&区间查询 #include<iostream> #include<iomanip> #include<cstring> #include<climits> #include<cmath> #include<cstdio> #include<cstdlib> #include<queue> #include<vector> #include<map> #include<algorithm> #include<string> #include<memory> using namespace std; const int e=100006; struct qq { int maxx; }tree[4*e];//线段树要开4倍的点的个数 int n,t,a,b; void updata(int l,int r,int root) { if(r<a || l>a) return; if(r==l) { tree[root].maxx=b; return; } int mid=(l+r)/2; updata(l,mid,root*2); updata(mid+1,r,root*2+1); tree[root].maxx=max(tree[root*2].maxx,tree[root*2+1].maxx); } int search(int l,int r,int root) { if(l>b || r<a) return(-999999999); if(l>=a && r<=b) return(tree[root].maxx); int mid=(l+r)/2; return(max( search(l,mid,root*2), search(mid+1,r,root*2+1))); } int main() { memset(tree,0,sizeof(tree)); cin>>n; for(int i=0;i<n;i++) { scanf("%d%d%d",&t,&a,&b); if(t==1) updata(1,n,1);//将点a的值改为b if(t==2) cout<< search(1,n,1) << endl;//查找区间a(含)到b(含)的最大值; } return 0; }
对一段区间的修改和查询:
//线段树 区间 修改&查询 #include<iostream> #include<iomanip> #include<cstring> #include<climits> #include<cmath> #include<cstdio> #include<cstdlib> #include<queue> #include<vector> #include<map> #include<algorithm> #include<string> #include<memory> using namespace std; const int e=100006; struct qq { int maxx,delta; }tree[4*e];//线段树要开4倍的点的个数 int n,t,a,b; void updata(int l,int r,int root)//更新数据 { if(b<l || r<a) return; if(l>=a && r<=b)//这句是核心,若当前区间包含于修改区间,就不往下传,(未传到叶子节点); { tree[root].maxx++; tree[root].delta++; return; } int mid=(l+r)/2,delta=tree[root].delta; tree[root*2].maxx+=delta; tree[root*2].delta+=delta; tree[root*2+1].maxx+=delta; tree[root*2+1].delta+=delta; tree[root].delta=0;//这句很关键,根的偏移量传递到子树后清零 updata(l,mid,root*2); updata(mid+1,r,root*2+1); tree[root].maxx=max( tree[root*2].maxx, tree[root*2+1].maxx); return; } int search(int l,int r,int root) { if(l>b || r<a) return(-99999999); if(l>=a && r<=b) return(tree[root].maxx); int mid=(l+r)/2,delta=tree[root].delta; tree[root*2].maxx+=delta; tree[root*2].delta+=delta; tree[root*2+1].maxx+=delta; tree[root*2+1].delta+=delta; tree[root].delta=0; //这句很关键,根的偏移量传递到子树后清零 return(max( search(l,mid,root*2), search(mid+1,r,root*2+1))); } int main() { memset(tree,0,sizeof(tree)); cin>>n; for(int i=0;i<n;i++) { scanf("%d%d%d",&t,&a,&b); if(t==1) updata(1,n,1); if(t==2) cout<< search(1,n,1) << endl; } return 0; }以下是做线段树题目时的易错点:
6、权值是在边上还是点上,这两种关系代码判断上有不同;
7、结构体赋初值的时候也要注意,根据所求的是最大还是最小还是和来判断;
8、线段树的左端点在数组中的下标一定要是1,而不是0。