1. 程式人生 > >線段樹大模板(區間更新,單點更新,查詢區間最值等等)

線段樹大模板(區間更新,單點更新,查詢區間最值等等)

#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; }