这个月要写4篇博客,工作量太大了,今天最后一天了,贴一下这几天整理过的线段树的模板吧。
int sum[maxn*4],minn[maxn*4],maxx[maxn*4],vis[maxn*4],Map[maxn],n;
//sum储存和,minn最小值,maxx最大值,vis作为求最值的标记数组,Map是原数组
建树
void built(int l,int r,int root)
{
if(l==r) //叶子结点
{
vis[root]=0;
sum[root]=Map[l];
maxx[root]=Map[l];
minn[root]=Map[l];
return;
}
int mid=(l+r)/2;
built(l,mid,root*2); //创建左子树
built(mid+1,r,root*2+1); //创建右子树
sum[root]=sum[root*2]+sum[root*2+1]; //根节点的和等于左右子树的和
maxx[root]=max(maxx[root*2],maxx[root*2+1]);
minn[root]=min(minn[root*2],minn[root*2+1]);
vis[root]=0;
}
更新操作
void push_up(int l,int r,int root,int x) //更新
{
vis[root]=x;
sum[root]=x*(r-l+1);
maxx[root]=x;
minn[root]=x;
}
void push_down(int l,int r,int root)
{
if(vis[root]==0)
return;
int mid=(l+r)/2;
push_up(l,mid,root*2,vis[root]);
push_up(mid+1,r,root*2+1,vis[root]);
vis[root]=0;
}
求区间和
long long query_sum(int L,int R,int l,int r,int root)
{
if(L<=l&&r<=R) //区间包含
return sum[root];
push_down(l,r,root);
int mid=(l+r)/2;
long long sum1=0,sum2=0;
if(L<=mid)
sum1=query_sum(L,R,l,mid,root*2); //区间在左子树
if(R>mid)
sum2=query_sum(L,R,mid+1,r,root*2+1); //在右子树
return sum1+sum2;
}
区间修改
void update(int L,int R,int x,int l,int r,int root)
{
if(L<=l&&R>=r)
{
push_up(l,r,root,x);
return ;
}
push_down(l,r,root); //向上更新
int mid=(l+r)/2;
if(L<=mid)
update(L,R,x,l,mid,root*2);
if(R>mid)
update(L,R,x,mid+1,r,root*2+1);
sum[root]=sum[root*2]+sum[root*2+1];
maxx[root]=max(maxx[root*2],maxx[root*2+1]);
minn[root]=min(minn[root*2],minn[root*2+1]);
}
单点修改
void Update(int k,int x,int l,int r,int root)
{
if(l==r)
{
Map[l]=x;
sum[root]=x;
maxx[root]=x;
minn[root]=x;
return;
}
int mid=(l+r)/2;
if(k<=mid)
Update(k,x,l,mid,root*2);
if(k>mid)
Update(k,x,mid+1,r,root*2+1);
sum[root]=sum[root*2]+sum[root*2+1];
maxx[root]=max(maxx[root*2],maxx[root*2+1]);
minn[root]=min(minn[root*2],minn[root*2+1]);
}
int query_max(int L,int R,int l,int r,int root)
{
if(L<=l&&r<=R)
return maxx[root];
push_down(l,r,root);
int mid=(l+r)/2;
int t1=-inf,t2=-inf;
if(L<=mid)
t1=query_max(L,R,l,mid,root*2);
if(R>mid)
t2=query_max(L,R,mid+1,r,root*2+1);
return max(t1,t2);
}
int query_min(int L,int R,int l,int r,int root)
{
if(L<=l&&r<=R)
return minn[root];
push_down(l,r,root);
int mid=(l+r)/2;
int t1=inf,t2=inf;
if(L<=mid)
t1=query_min(L,R,l,mid,root*2);
if(R>mid)
t2=query_min(L,R,mid+1,r,root*2+1);
return min(t1,t2);
}
最后综合一下
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e5+5;
int sum[maxn*4],minn[maxn*4],maxx[maxn*4],vis[maxn*4],Map[maxn],n;
//sum储存和,minn最小值,maxx最大值,vis作为求最值的标记数组,Map是原数组
void built(int l,int r,int root)
{
if(l==r) //叶子结点
{
vis[root]=0;
sum[root]=Map[l];
maxx[root]=Map[l];
minn[root]=Map[l];
return;
}
int mid=(l+r)/2;
built(l,mid,root*2); //创建左子树
built(mid+1,r,root*2+1); //创建右子树
sum[root]=sum[root*2]+sum[root*2+1]; //根节点的和等于左右子树的和
maxx[root]=max(maxx[root*2],maxx[root*2+1]);
minn[root]=min(minn[root*2],minn[root*2+1]);
vis[root]=0;
}
void push_up(int l,int r,int root,int x) //更新
{
vis[root]=x;
sum[root]=x*(r-l+1);
maxx[root]=x;
minn[root]=x;
}
void push_down(int l,int r,int root)
{
if(vis[root]==0)
return;
int mid=(l+r)/2;
push_up(l,mid,root*2,vis[root]);
push_up(mid+1,r,root*2+1,vis[root]);
vis[root]=0;
}
void update(int L,int R,int x,int l,int r,int root)
{
if(L<=l&&R>=r)
{
push_up(l,r,root,x);
return ;
}
push_down(l,r,root); //向上更新
int mid=(l+r)/2;
if(L<=mid)
update(L,R,x,l,mid,root*2);
if(R>mid)
update(L,R,x,mid+1,r,root*2+1);
sum[root]=sum[root*2]+sum[root*2+1];
maxx[root]=max(maxx[root*2],maxx[root*2+1]);
minn[root]=min(minn[root*2],minn[root*2+1]);
}
long long query_sum(int L,int R,int l,int r,int root)
{
if(L<=l&&r<=R) //区间包含
return sum[root];
push_down(l,r,root);
int mid=(l+r)/2;
long long sum1=0,sum2=0;
if(L<=mid)
sum1=query_sum(L,R,l,mid,root*2); //区间在左子树
if(R>mid)
sum2=query_sum(L,R,mid+1,r,root*2+1); //在右子树
return sum1+sum2;
}
int query_max(int L,int R,int l,int r,int root)
{
if(L<=l&&r<=R)
return maxx[root];
push_down(l,r,root);
int mid=(l+r)/2;
int t1=-inf,t2=-inf;
if(L<=mid)
t1=query_max(L,R,l,mid,root*2);
if(R>mid)
t2=query_max(L,R,mid+1,r,root*2+1);
return max(t1,t2);
}
int query_min(int L,int R,int l,int r,int root)
{
if(L<=l&&r<=R)
return minn[root];
push_down(l,r,root);
int mid=(l+r)/2;
int t1=inf,t2=inf;
if(L<=mid)
t1=query_min(L,R,l,mid,root*2);
if(R>mid)
t2=query_min(L,R,mid+1,r,root*2+1);
return min(t1,t2);
}
void Update(int k,int x,int l,int r,int root)
{
if(l==r)
{
Map[l]=x;
sum[root]=x;
maxx[root]=x;
minn[root]=x;
return;
}
int mid=(l+r)/2;
if(k<=mid)
Update(k,x,l,mid,root*2);
if(k>mid)
Update(k,x,mid+1,r,root*2+1);
sum[root]=sum[root*2]+sum[root*2+1];
maxx[root]=max(maxx[root*2],maxx[root*2+1]);
minn[root]=min(minn[root*2],minn[root*2+1]);
}
int main()
{
int i,j,k,x,y,z,t;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>Map[i];
}
built(1,n,1);
long long ans;
int m1,m2;
cout<<"1、区间求和\n2、区间求最值\n3、单点修改\n4、区间修改\n";
while(cin>>x)
{
switch(x)
{
case 1:
cin>>y>>z;
ans=query_sum(y,z,1,n,1);
cout<<ans<<endl;
break;
case 2:
cin>>y>>z;
m1=query_max(y,z,1,n,1);
m2=query_min(y,z,1,n,1);
cout<<m1<<"***"<<m2<<endl;
break;
case 3:
cin>>y>>z;
Update(y,z,1,n,1);
break;
case 4:
cin>>y>>z>>t;
update(y,z,t,1,n,1);
break;
}
}
return 0;
}