【CF52C】Circular RMQ(線段樹區間加減,區間最值)

給定一個循環數組a0, a1, a2, …, an-1,如今對他們有兩個操做:數組

Inc(le, ri, v)表示區間[le, ri]範圍的數值增長vide

Rmq(le, ri)表示詢問區間[le, ri]範圍內的最小值ui

注意,這個是循環數組,因此若是n=5, le=3, ri=1,那麼詢問的是a3, a4, a0, a1中的最小值。spa

幫助BSNY寫一個程序完成上述操做。xml

【數據規模和約定】string

 

1<= n <=200000   0<=Q<=200000it


-10^6<= ai <=10^6   0<=le, ri<=n-1   -10^6<= v <=10^6io

 

簡單的線段樹區間加減,區間求最值。function

注意max已經超過maxlongintclass

 

 

  1 const oo=1000000000000000000;
  2 var tree:array[1..1000000]of record
  3                               a,s:int64;
  4                              end;
  5     a:array[1..1000000]of int64;
  6     n,q,len,x,y,z,p:int64;
  7     ch,s:string;
  8     i,j,k:longint;
  9 
 10 
 11 
 12 procedure pushdown(p:int64);
 13 begin
 14  tree[p<<1].s:=tree[p<<1].s+tree[p].a;
 15  tree[p<<1].a:=tree[p<<1].a+tree[p].a;
 16  tree[p<<1+1].s:=tree[p<<1+1].s+tree[p].a;
 17  tree[p<<1+1].a:=tree[p<<1+1].a+tree[p].a;
 18  tree[p].a:=0;
 19 end;
 20 
 21 procedure pushup(p:int64);
 22 begin
 23  if tree[p<<1].s<tree[p<<1+1].s then tree[p].s:=tree[p<<1].s
 24   else tree[p].s:=tree[p<<1+1].s;
 25 // tree[p].s:=min(tree[p<<1].s,tree[p<<1+1].s);
 26 end;
 27 
 28 procedure build(l,r,p:int64);
 29 var mid:int64;
 30 begin
 31  if l=r then
 32  begin
 33   tree[p].s:=a[l];
 34   tree[p].a:=0;
 35   exit;
 36  end;
 37  mid:=(l+r)>>1;
 38  if l<=mid then build(l,mid,p<<1);
 39  if r>mid then build(mid+1,r,p<<1+1);
 40  pushup(p);
 41 end;
 42 
 43 function query(l,r,x,y,p:int64):int64;
 44 var mid:int64;t,ret:int64;
 45 begin
 46  if (x<=l)and(y>=r) then exit(tree[p].s);
 47  pushdown(p);
 48  mid:=(l+r)>>1;
 49  ret:=oo;
 50  //query:=oo;
 51  if x<=mid then ret:=query(l,mid,x,y,p<<1);
 52  if y>mid then
 53  begin
 54   t:=query(mid+1,r,x,y,p<<1+1);
 55   if t<ret then ret:=t; //query:=min(query,t);
 56  end;
 57  exit(ret);
 58 end;
 59 
 60 procedure update(l,r,x,y,v,p:int64);
 61 var mid:int64;
 62 begin
 63  if (x<=l)and(y>=r) then
 64  begin
 65   tree[p].s:=tree[p].s+v;
 66   tree[p].a:=tree[p].a+v;
 67   exit;
 68  end;
 69  pushdown(p);
 70  mid:=(l+r)>>1;
 71  if x<=mid then update(l,mid,x,y,v,p<<1);
 72  if y>mid then update(mid+1,r,x,y,v,p<<1+1);
 73  pushup(p);
 74 end;
 75 
 76 begin
 77 
 78  readln(n);
 79  for i:=1 to n do read(a[i]);
 80  for i:=1 to n<<2 do tree[i].s:=oo;
 81  build(1,n,1);
 82  readln(q);
 83  for i:=1 to q do
 84  begin
 85   readln(ch); len:=length(ch);
 86   p:=0;
 87   for j:=1 to len do
 88    if ch[j]=' ' then inc(p);
 89   if p=1 then
 90   begin
 91    x:=0;
 92    j:=0;
 93    repeat
 94     inc(j);
 95     if ch[j]<>' ' then x:=x*10+ord(ch[j])-ord('0')
 96      else break;
 97    until j=len;
 98    y:=0;
 99    repeat
100     inc(j);
101     if ch[j]<>' ' then y:=y*10+ord(ch[j])-ord('0')
102      else break;
103    until j=len;
104    inc(x); inc(y);
105    if x<=y then writeln(query(1,n,x,y,1))
106     else
107      if query(1,n,x,n,1)<query(1,n,1,y,1) then writeln(query(1,n,x,n,1))
108       else writeln(query(1,n,1,y,1));
109   end
110    else
111    begin
112     x:=0;
113     j:=0;
114     repeat
115      inc(j);
116      if ch[j]<>' ' then x:=x*10+ord(ch[j])-ord('0')
117       else break;
118     until j=len;
119     y:=0;
120     repeat
121      inc(j);
122      if ch[j]<>' ' then y:=y*10+ord(ch[j])-ord('0')
123       else break;
124     until j=len;
125     s:='';
126     for k:=j+1 to len do s:=s+ch[k];
127     val(s,z);
128     inc(x); inc(y);
129     if x<=y then update(1,n,x,y,z,1)
130      else
131      begin
132       update(1,n,x,n,z,1);
133       update(1,n,1,y,z,1);
134      end;
135    end;
136  end;
137 
138 end.