【模板】区间修改-线段树

来源:互联网 发布:2016年制造业数据 编辑:程序博客网 时间:2024/05/16 10:07

题目描述
在N个数A1…An组成的序列上进行M次操作,操作有两种:
(1)1 L R C:表示把A[L]到A[R]增加C(C的绝对值不超过10000);
(2)2 L R:询问A[L]到A[R]之间的最大值。

输入
第一行输入N,表示序列的长度,接下来N行输入原始序列;接下来一行输入M表示操作的次数,接下来M行,每行为1 L R C或2 L R

输出
对于每个操作(2)输出对应的答案。

样例输入
5
1
2
3
4
5
3
2 1 4
1 1 3 3
2 3 5

样例输出
4
6

提示
对于100%的数据满足:1<=N,M,L,R<=100000。所有的数都在int的范围内。

代码:

#include<bits/stdc++.h> using namespace std; struct ldx {     int x,y,u,v; }f[400005]; int opt,n,m,lx,ly,lc,s[100005]; void js(int num,int a,int b) {     f[num].x=a;f[num].y=b;f[num].v=0;     if(a==b) {f[num].u=s[a];return;}     int mid=a+b>>1;     js(num<<1,a,mid);     js(num<<1|1,mid+1,b);     f[num].u=max(f[num<<1].u,f[num<<1|1].u); } void res(int num) {     if(f[num].x>=lx && f[num].y<=ly)     {       f[num].v+=lc;       return ;    }    f[num<<1].v+=f[num].v;    f[num<<1|1].v+=f[num].v;    f[num].v=0;    int mid=f[num].x+f[num].y>>1;     if(ly<=mid) res(num<<1);    else if(lx>mid) res(num<<1|1);    else {res(num<<1);res(num<<1|1);}    f[num].u=max(f[num<<1].u+f[num<<1].v,f[num<<1|1].u+f[num<<1|1].v); } int ch(int num) {    if(f[num].x>=lx && f[num].y<=ly) return f[num].u+f[num].v;    f[num<<1].v+=f[num].v;    f[num<<1|1].v+=f[num].v;    f[num].v=0;    int ans,mid=f[num].x+f[num].y>>1;     if(ly<=mid) ans=ch(num<<1);    else if(lx>mid) ans=ch(num<<1|1);    else ans=max(ch(num<<1),ch(num<<1|1));    f[num].u=max(f[num<<1].u+f[num<<1].v,f[num<<1|1].u+f[num<<1|1].v);       return ans; } int main() {     scanf("%d",&n);      for(int i=1;i<=n;i++) scanf("%d",&s[i]);     js(1,1,n);     scanf("%d",&m);     for(int i=1;i<=m;i++)     {        scanf("%d%d%d",&opt,&lx,&ly);            if(opt==2) printf("%d\n",ch(1));         else        {           scanf("%d",&lc);           res(1);        }         }     return 0; }