線段樹大模板(區間更新,單點更新,查詢區間最值等等)
阿新 • • 發佈:2018-12-24
#include <bits/stdc++.h>
#define MAXN 100010
#define inf 0x3f3f3f3f
using namespace std;
struct node{
int l,r;//區間[l,r]
int add;//區間的延時標記
int sum;//區間和
int mx; //區間最大值
int mn; //區間最小值
}tree[MAXN<<2];//一定要開到4倍多的空間
void pushup(int index){
tree[index].sum = tree[index<<1].sum+tree[index <<1|1].sum;
tree[index].mx = max(tree[index<<1].mx,tree[index<<1|1].mx);
tree[index].mn = min(tree[index<<1].mn,tree[index<<1|1].mn);
}
void pushdown(int index){
//說明該區間之前更新過
//要想更新該區間下面的子區間,就要把上次更新該區間的值向下更新
if(tree[index].add > 0){
//替換原來的值
/*
tree[index <<1].sum = (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
tree[index<<1|1].sum = (tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
tree[index<<1].mx = tree[index].add;
tree[index<<1|1].mx = tree[index].add;
tree[index <<1].mn = tree[index].add;
tree[index<<1|1].mn = tree[index].add;
tree[index<<1].add = tree[index].add;
tree[index<<1|1].add = tree[index].add;
tree[index].add = 0;*/
//在原來的值的基礎上加上val
tree[index<<1].sum += (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
tree[index<<1|1].sum +=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
tree[index<<1].mx += tree[index].add;
tree[index<<1|1].mx += tree[index].add;
tree[index<<1].mn += tree[index].add;
tree[index<<1|1].mn += tree[index].add;
tree[index<<1].add += tree[index].add;
tree[index<<1|1].add += tree[index].add;
tree[index].add = 0;
}
}
void build(int l,int r,int index){
tree[index].l = l;
tree[index].r = r;
tree[index].add = 0;//剛開始一定要清0
if(l == r){
scanf("%d",&tree[index].sum);
tree[index].mn = tree[index].mx = tree[index].sum;
return ;
}
int mid = (l+r)>>1;
build(l,mid,index<<1);
build(mid+1,r,index<<1|1);
pushup(index);
}
void updata(int l,int r,int index,int val){
if(l <= tree[index].l && r >= tree[index].r){
/*把原來的值替換成val,因為該區間有tree[index].r-tree[index].l+1
個數,所以區間和 以及 最值為:
*/
/*tree[index].sum = (tree[index].r-tree[index].l+1)*val;
tree[index].mn = val;
tree[index].mx = val;
tree[index].add = val;//延時標記*/
//在原來的值的基礎上加上val,因為該區間有tree[index].r-tree[index].l+1
//個數,所以區間和 以及 最值為:
tree[index].sum += (tree[index].r-tree[index].l+1)*val;
tree[index].mn += val;
tree[index].mx += val;
tree[index].add += val;//延時標記
return ;
}
pushdown(index);
int mid = (tree[index].l+tree[index].r)>>1;
if(l <= mid){
updata(l,r,index<<1,val);
}
if(r > mid){
updata(l,r,index<<1|1,val);
}
pushup(index);
}
int query(int l,int r,int index){
if(l <= tree[index].l && r >= tree[index].r){
//return tree[index].sum;
return tree[index].mx;
//return tree[index].mn;
}
pushdown(index);
int mid = (tree[index].l+tree[index].r)>>1;
int ans = 0;
int Max = 0;
int Min = inf;
if(l <= mid){
ans += query(l,r,index<<1);
Max = max(query(l,r,index<<1),Max);
Min = min(query(l,r,index<<1),Min);
}
if(r > mid){
ans += query(l,r,index<<1|1);
Max = max(query(l,r,index<<1|1),Max);
Min = min(query(l,r,index<<1|1),Min);
}
//return ans;
return Max;
//return Min;
}
int main()
{
int n,m,q,x,y,z;
while(~scanf("%d%d",&n,&m)){
build(1,n,1);
while(m--){
scanf("%d",&q);
if(q == 1){
cout<<"查詢:(x,y)"<<endl;
scanf("%d %d",&x,&y);
cout<<query(x,y,1)<<endl;
}
else{
cout<<"更新(x,y)為z:"<<endl;
scanf("%d %d %d",&x,&y,&z);
updata(x,y,1,z);
for(int i = 1; i <= n; ++i){
printf("a[%d] = %d\n",i,query(i,i,1));
}
}
}
}
return 0;
}