最全基础区间线段树模板
以下这个板子稍微理解以下完全可以盲敲,
维护包括了最值,区间和(当然 能区间分治的信息都能维护,比如集合之类的) 更新包括了区间替换和区间加减 两种。暂时只测试了最大值,如果有错欢迎留言。
/*既要维护Min,又要维护区间替换的值,又要查询一个点的值的话。要加一个V数组,if add[rt]==V[rt] 说明标记没有下推,这个区间的值都是V[rt],所以Min[rt]=V[rt]等else 说明这个区间的值不完全一样,需要继续下推标记。直到l==r。更新 上推还是照样上推*/#include#define rep(i,l,r) for(int i=l;i =l;i--)#define lc rt<<1#define lson l,m,rt<<1#define rc rt<<1|1#define rson m+1,r,rt<<1|1#define mp make_pair#define pb push_back#define all(x) x.begin(),x.end()using namespace std;typedef long long ll;typedef pair pii;const int INF=0x3f3f3f3f;using namespace std;int n,m,k;const int N=1e5+10;int A[N];//线段树struct segT{ static const int segN=1e5+10; int Max[segN<<2];//Max[segN<<2],Sum[segN<<2],V[segN<<2];//min,max,sum,val int add[segN<<2]; void pushup(int rt){ Max[rt]=max(Max[lc],Max[rc]); } void build(int l,int r,int rt){ add[rt]=0; if(l==r){ Max[rt]=A[l]; return; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } /************* *区间替换用=v,区间更新用+=v *add,Max,Max(+)=v *Sum[lc](+)=(m-l+1)*v *Sum[rc](+)=(r-m)*v *******************/ //void pushdown(int l,int r,int rt){ void pushdown(int rt){ //int m=(l+r)>>1; if(add[rt]){ int v=add[rt]; add[rt]=0; Max[lc]+=v; Max[rc]+=v; add[lc]+=v; add[rc]+=v; } } void update(int L,int R,int v,int l,int r,int rt){ if(L<=l&&r<=R){ Max[rt]+=v; add[rt]+=v; return; } pushdown(rt); int m=(l+r)>>1; if(L<=m)update(L,R,v,lson); if(m+1<=R)update(L,R,v,rson); pushup(rt); } //如果要返回的参数不止一个,就改成void 在第一个if中更新信息, //然后return,比如还要记录最大值的下标 int query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ return Max[rt]; } pushdown(rt); int m=(l+r)>>1; int ret=-INF; if(L<=m)ret=max(ret,query(L,R,lson)); if(m+1<=R)ret=max(ret,query(L,R,rson)); return ret; }};segT seg1;int main(){ //freopen("in.txt","r",stdin); int A[N]; int n,m,x,y,v,op; while(~scanf("%d",&n)){ for(int i=1;i<=n;i++) scanf("%d",&A[i]); seg1.build(1,n,1); while(scanf("%d",&op)){ if(op==1){ scanf("%d%d%d",&x,&y,&v); seg1.update(x,y,v,1,n,1); } else if(op==2){ scanf("%d%d",&x,&y); cout< <