题目:有n个兵营(n<=50000),一开始所有兵营都有一定数量的人,然后有三种操作:一种是某个兵营加上一定数量的人,一种是某个兵营减去一定数量的人,一种是统计一个区间内的兵营总共有多少人。操作数量不超过40000。
分析:这道题的数据量很大,如果用朴素算法,每次操作的时间复杂度是O(n),由于有50000次操作,肯定会超时,这时就要用线段树来做,每次操作的时间复杂度是O(log n)。
一定要注意的是这题的读入非常坑爹,要控制好各种空格和换行,不然会w到你****。前车之鉴啊!
下面附代码:
var w,l,n,x,y,i:longint; t:array[1..150000,1..3] of longint; s:string; r:char; procedure hehe(d,l,r:longint); var m:longint; begin t[d,1]:=l; t[d,2]:=r; t[d,3]:=0; if l=r then exit; m:=(l+r) div 2; hehe(d*2,l,m); hehe(d*2+1,m+1,r); end; procedure work(d,x,y:longint); var m:longint; begin t[d,3]:=t[d,3]+y; if t[d,1]=t[d,2] then exit; m:=(t[d,1]+t[d,2]) div 2; if x<=m then work(d*2,x,y) else work(d*2+1,x,y); end; function count(d,l,r:longint):longint; var m:longint; begin if (t[d,1]=l)and(t[d,2]=r) then exit(t[d,3]); m:=(t[d,1]+t[d,2]) div 2; if r<=m then count:=count(d*2,l,r) else if l>m then count:=count(d*2+1,l,r) else count:=count(d*2,l,m)+count(d*2+1,m+1,r); end; begin readln(w); for l:=1 to w do begin writeln('Case ',l,':'); readln(n); hehe(1,1,n); for i:=1 to n do begin read(x); work(1,i,x); end; readln; s:=''; read(r); while (r<>' ')and(not eoln) do begin s:=s+r; read(r); end; while s[1]<>'E' do begin readln(x,y); case s[1] of 'A':work(1,x,y); 'S':work(1,x,-y); 'Q':writeln(count(1,x,y)); end; read(r); s:=''; while (r<>' ')and(not eoln) do begin s:=s+r; read(r); end; end; readln; end; end.