zoukankan      html  css  js  c++  java
  • CodeVS 4927-线段树练习5

    原题

    题目描述 Description

    有n个数和5种操作:

    add a b c:把区间[a,b]内的所有数都增加c;

    set a b c:把区间[a,b]内的所有数都设为c;

    sum a b:查询区间[a,b]的区间和;

    max a b:查询区间[a,b]的最大值;

    min a b:查询区间[a,b]的最小值.

    输入描述 Input Description

    第一行两个整数n,m,第二行n个整数表示这n个数的初始值.

    接下来m行操作,同题目描述.

    输出描述 Output Description

    对于所有的sum、max、min询问,一行输出一个答案

    样例输入 Sample Input

    10 6

    3 9 2 8 1 7 5 0 4 6

    add 4 9 4

    set 2 6 2

    add 3 8 2

    sum 2 10

    max 1 7

    min 3 6

    样例输出 Sample Output

    49

    11

    4

    数据范围及提示 Data Size & Hint

    10%:1<n,m<=10

    30%:1<n,m<=10000

    100%:1<n,m<=100000

    保证中间结果在long long(C/C++)、int64(pascal)范围内

    题解

    思路不难,可是码农题调起来就是变态,一搞就是一两天...毕竟这是一棵功能完备的线段树.

    这题最难的就是add和set两个Lazy标记.

    要先明确一点,就是set的Lazy优先级大于add的Lazy,因为不管你前面的操作再多,一个set下去也必须全部清除.

    因此:在标记set的Lazy的时候,就要把add的Lazy清除,并更新该节点的set值;在标记add的Lazy的时候,就要判断一下,如果改点已经是set过了的,就要将set加上要add的数,并把改点的add Lazy清零.

    在标记set或add的过程中,在子程序的最前端一定要有一个判断,如果路上的搜索到的点所表示的区间已经被set过了,那么一定要先将该点的set下传,并更新该点的sum/max/min值.如果该点没被set过且不是目标区间且del不为0,那么将该点的del下传,并更新该点的sum/max/min值.还有一点很重要,就是一个节点不可能同时存在set的Lazy与add的Lazy.

    查询sum/max/min的时候,在子程序的最前端依旧要有一个判断,如果该点所表示的区间已经被set过了,那么一定要先将该点的set下传,并更新该点的sum/max/min值.

    这题子程序贼多...但如果没有的话,在下传set或add时就会特别混乱=_=.

    下面是代码:

    uses math;
    var sum,st,del,mx,mn:array[1..800000] of int64;
    var a:array[1..100000] of int64; 
    var en:array[1..800000] of boolean;
    var n,m,x,y,z:int64;
    var c1,c2,c3,c4:char;
    var j,i:longint;
    function calcsum(h,l,r:int64):int64;
    var m,p:int64;
    begin
      m:=(l+r)>>1;
      if en[h<<1] then p:=st[h<<1]*(m-l+1) else p:=sum[h<<1]+del[h<<1]*(m-l+1);
      if en[h<<1+1] then inc(p,st[h<<1+1]*(r-m)) else inc(p,sum[h<<1+1]+del[h<<1+1]*(r-m));
      exit(p);
    end;
    function calcmax(h,l,r:int64):int64;
    var p:int64;
    begin
      if en[h<<1] then p:=st[h<<1] else p:=mx[h<<1]+del[h<<1];
      if en[h<<1+1] then p:=max(p,st[h<<1+1]) else p:=max(p,mx[h<<1+1]+del[h<<1+1]);
      exit(p);
    end;
    function calcmin(h,l,r:int64):int64;
    var p:int64;
    begin
      if en[h<<1] then p:=st[h<<1] else p:=mn[h<<1]+del[h<<1];
      if en[h<<1+1] then p:=min(p,st[h<<1+1]) else p:=min(p,mn[h<<1+1]+del[h<<1+1]);
      exit(p);
    end;
    procedure build(h,l,r:int64);
    var m:int64;
    begin
      if l=r then begin sum[h]:=a[l];mx[h]:=a[l];mn[h]:=a[l];exit; end;
      m:=(l+r)>>1;
      build(h<<1,l,m);build(h<<1+1,m+1,r);
      sum[h]:=sum[h<<1]+sum[h<<1+1];
      mx[h]:=max(mx[h<<1],mx[h<<1+1]);
      mn[h]:=min(mn[h<<1],mn[h<<1+1]);
    end;
    procedure downset(h,l,r:int64);
    begin
      st[h<<1]:=st[h];st[h<<1+1]:=st[h];
      en[h<<1]:=true;en[h<<1+1]:=true;en[h]:=false;
      del[h<<1]:=0;del[h<<1+1]:=0;
      mx[h]:=st[h];mn[h]:=st[h];sum[h]:=st[h]*(r-l+1);
    end;
    procedure downdel(h,l,r:int64);
    begin
      if en[h<<1] then inc(st[h<<1],del[h]) else del[h<<1]:=del[h<<1]+del[h];
      if en[h<<1+1] then inc(st[h<<1+1],del[h]) else del[h<<1+1]:=del[h<<1+1]+del[h];
      inc(mx[h],del[h]);inc(mn[h],del[h]);inc(sum[h],del[h]*(r-l+1));
      del[h]:=0;
    end;
    procedure add(h,l,r,x,y,c:int64);
    var m:int64;
    begin
      if en[h] then downset(h,l,r);
      if (l>=x)and(r<=y) then
      begin
        del[h]:=del[h]+c;
        if en[h] then begin st[h]:=st[h]+c;del[h]:=0; end;
        exit;
      end;
      m:=(l+r)>>1;
      if del[h]>0 then downdel(h,l,r);
      if x<=m then add(h<<1,l,m,x,y,c);
      if y>m then add(h<<1+1,m+1,r,x,y,c);
      sum[h]:=calcsum(h,l,r);mx[h]:=calcmax(h,l,r);mn[h]:=calcmin(h,l,r);
    end;
    procedure setup(h,l,r,x,y,num:int64);
    var m,p:int64;
    begin
      if en[h] then downset(h,l,r);
      if (l>=x)and(r<=y) then
      begin
        st[h]:=num;en[h]:=true;
        del[h]:=0;exit;
      end;
      if del[h]>0 then downdel(h,l,r);
      m:=(l+r)>>1;
      if x<=m then setup(h<<1,l,m,x,y,num);
      if y>m then setup(h<<1+1,m+1,r,x,y,num);
      sum[h]:=calcsum(h,l,r);mx[h]:=calcmax(h,l,r);mn[h]:=calcmin(h,l,r);
    end;
    function asksum(h,l,r,x,y:int64):int64;
    var m,p:int64;
    begin
      if en[h] then downset(h,l,r);p:=0;
      if (l>=x)and(r<=y) then if en[h] then p:=p+st[h]*(r-l+1) else p:=p+sum[h]+del[h]*(r-l+1) else
      begin
        if del[h]>0 then downdel(h,l,r);
        m:=(l+r)>>1;
        if x<=m then p:=p+asksum(h<<1,l,m,x,y);
        if y>m then p:=p+asksum(h<<1+1,m+1,r,x,y);
      end;
      exit(p);
    end;
    function askmax(h,l,r,x,y:int64):int64;
    var m,p:int64;
    begin
      p:=-10000000;
      if en[h] then downset(h,l,r);
      if (l>=x)and(r<=y) then if en[h] then p:=max(p,st[h]) else p:=max(p,mx[h]+del[h]) else
      begin
        if del[h]>0 then downdel(h,l,r);
        m:=(l+r)>>1;
        if x<=m then p:=max(p,askmax(h<<1,l,m,x,y));
        if y>m then p:=max(p,askmax(h<<1+1,m+1,r,x,y));
      end;
      exit(p);
    end;
    function askmin(h,l,r,x,y:int64):int64;
    var m,p:int64;
    begin
      p:=10000000;
      if en[h] then downset(h,l,r);
      if (l>=x)and(r<=y) then if en[h] then p:=min(p,st[h]) else p:=min(p,mn[h]+del[h]) else
      begin
        if del[h]>0 then downdel(h,l,r);
        m:=(l+r)>>1;
        if x<=m then p:=min(p,askmin(h<<1,l,m,x,y));
        if y>m then p:=min(p,askmin(h<<1+1,m+1,r,x,y));
      end;
      exit(p);
    end;
    begin
      readln(n,m);
      for i:=1 to n do read(a[i]);readln;
      build(1,1,n);
      for i:=1 to m do
      begin
        read(c1,c2,c3,c4);
        if c2='e' then begin readln(x,y,z);setup(1,1,n,x,y,z); end;
        if c2='d' then begin readln(x,y,z);add(1,1,n,x,y,z); end;
        if c2='u' then begin readln(x,y);writeln(asksum(1,1,n,x,y)); end;
        if c2='a' then begin readln(x,y);writeln(askmax(1,1,n,x,y)); end;
        if c2='i' then begin readln(x,y);writeln(askmin(1,1,n,x,y)); end;
      end;
    end.

     

  • 相关阅读:
    HeapSpray初窥(2014.12)
    CVE-2014-4115漏洞分析(2014.11)
    【原创】oracle提权执行命令工具oracleShell v0.1
    【原创】贴个dirtycow(脏牛漏洞)不死机的exploit
    【CVE-2016-10009】OpenSSH < 7.4
    关于elasticsearch和kibana的时区和日期问题
    这是我写过的最长的正则表达式,没有之一
    三生缘
    【原创】JEECMS v6~v7任意文件上传漏洞(2)
    【原创】JEECMS v6~v7任意文件上传漏洞(1)
  • 原文地址:https://www.cnblogs.com/HAdolf-HQY/p/6512021.html
Copyright © 2011-2022 走看看