1960. 最大值2

Description

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

Input

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

Output

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

Sample Input

5
1
2
3
4
5
3
2 1 4
1 1 3 3
2 3 5

Sample Output

4
6

Data Constraint

Hint

【限制】
  保证序列中的所有的数都在longint范围内

Solution

直接线段树+区间修改即可。

Code1

#include<cstdio>
using namespace std;
long long a[100020],f[500020],g[500020],ans,z;
int n,m,k,x,y;
int max(long long a,long long b){
    if (a>b) return a;
    else return b;
}
void add(int x,int l,int r){
    if(!g[x]) return;
    if(l!=r){g[x*2]+=g[x];g[x*2+1]+=g[x];f[x*2]+=g[x];f[x*2+1]+=g[x];}
    g[x]=0;
}
void build(int x,int l,int r){
    int m;
    if (l==r) f[x]=a[l];
    else{
        m=(l+r)/2;
        build(x*2,l,m);build(x*2+1,m+1,r);
        f[x]=max(f[x*2],f[x*2+1]);
    }
}
void change(int x,int s,int t,int l,int r,long long k){
    if (l==s&&t==r) {g[x]+=k;f[x]+=k;}
    else{
        add(x,s,t);
        int m=(s+t)/2;
        if (r<=m) change(x*2,s,m,l,r,k);
        else if (l>m) change(x*2+1,m+1,t,l,r,k);
        else{
            change(x*2,s,m,l,m,k);
            change(x*2+1,m+1,t,m+1,r,k);
        }
        f[x]=max(f[x*2],f[x*2+1]);
    }
}
void find(int x,int s,int t,int l,int r){
    int m;
    if ((s==l)and(t==r)) ans=max(ans,f[x]);
    else{
        add(x,s,t);
        m=(s+t)/2;
        if (r<=m) find(x*2,s,m,l,r);
        else if (l>m) find(x*2+1,m+1,t,l,r);
        else{
            find(x*2,s,m,l,m);
            find(x*2+1,m+1,t,m+1,r);
        }
    }
}
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
    build(1,1,n);
    scanf("%d",&m);
    for (int i=1;i<=m;i++){
        scanf("%d%d%d",&k,&x,&y);
        if (k==1){
            scanf("%lld",&z);
            change(1,1,n,x,y,z);
        }
        else{
            ans=-2147483647;
            find(1,1,n,x,y);
            printf("%lld\n",ans);
        }
    }
    return 0;
}

Code2

uses math;
var
    i,j,n,m,s,x,y,z,w:longint;
    f,a,c:array[0..310000]of longint;
procedure change(x,y,l,r,k,v:longint);
var m:longint;
begin
     if (x=l)and(y=r) then
     begin
          inc(c[v],k); inc(f[v],k);
     end else begin
         inc(f[v*2],c[v]); inc(c[v*2],c[v]);
         inc(f[v*2+1],c[v]); inc(c[v*2+1],c[v]);
         c[v]:=0; m:=(x+y)div 2;
         if r<=m then change(x,m,l,r,k,v*2)
         else begin
              if l>m then change(m+1,y,l,r,k,v*2+1)
              else begin
                   change(x,m,l,m,k,v*2);
                   change(m+1,y,m+1,r,k,v*2+1);
              end;
         end; f[v]:=max(f[v*2],f[v*2+1]);
     end;
end;
procedure tree(l,r,x:longint);
var mid:longint;
begin
     if l=r then f[x]:=a[l]
     else begin
          mid:=(l+r)div 2;
          tree(l,mid,x*2); tree(mid+1,r,x*2+1);
          f[x]:=max(f[2*x],f[2*x+1]);
     end;
end;
procedure find(x,y,l,r,v:longint);
var m:longint;
begin
     if (x=l)and(y=r) then s:=max(s,f[v])
     else begin
          inc(f[v*2],c[v]); inc(c[v*2],c[v]);
          inc(f[v*2+1],c[v]); inc(c[v*2+1],c[v]);
          c[v]:=0; m:=(x+y)div 2;
          if r<=m then find(x,m,l,r,v*2)
          else begin
               if l>m then find(m+1,y,l,r,v*2+1)
               else begin
                    find(x,m,l,m,v*2);
                    find(m+1,y,m+1,r,v*2+1);
               end;
          end;
     end;
end;
begin
      readln(n);
      for i:=1 to n do readln(a[i]);
      tree(1,n,1); readln(m);
      for i:=1 to m do begin
           read(z);
           if z=1 then
           begin
                readln(x,y,w);
                change(1,n,x,y,w,1);
           end  else begin
                readln(x,y); s:=-maxlongint;
                find(1,n,x,y,1); writeln(s);
           end;
      end;
end.


作者:zsjzliziyang
QQ:1634151125
转载及修改请注明
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/81914293

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值