题目: | 夏夜砍树 | |
来源: | Tyvj 1324 | |
题目大意: | 给出N个数,M次操作,每次输出区间(a,b)内所有值的和*3.14,并且删掉 (a+b)div 2 这个数 | |
数据范围: | n<=200000,m<=200000 | |
样例: | 5 1 2 3 4 5 2 1 4 2 4 | 31.40 21.98 |
做题思路: | 线段树,每次查找完再把0插入到(a+b)div 2 位置上就好,记得*3.14 | |
知识点: | 线段树 |
const MaxN=200010;
type
tre=record
l,r,lc,rc,sum:longint;{<左右边界、左右儿子、区间和>}
end;//tre
var
tree:array[0..MaxN*4] of tre;
n,m,i,j,x,a,b,root,tot,ans,p:longint;
procedure build(vart:longint;l,r:longint);{<建树>}
begin
inc(tot);t:=tot;
tree[t].l:=l;tree[t].r:=r;
tree[t].sum:=0;
ifl<r then
begin
build(tree[t].lc,l,(l+r)div 2);
build(tree[t].rc,(l+r)div 2+1,r);
end;//if
end;
procedure insert(t,i:longint);{<把x插入到i位置>}
begin
ift=0 then exit;
iftree[t].l=tree[t].r then
begin
tree[t].sum:=x;
exit;
end;
iftree[tree[t].lc].r>=i then insert(tree[t].lc,i)
else insert(tree[t].rc,i);
tree[t].sum:=tree[tree[t].lc].sum+tree[tree[t].rc].sum;
end;
procedure find(t,l,r:longint);{<查找>}
begin
ift=0 then exit;
if(tree[t].l=l)and(tree[t].r=r) then
begin
inc(ans,tree[t].sum);{<由于可能跨越子树,所以要把找到的都加起来>}
exit;
end;
iftree[tree[t].lc].r>=r then find(tree[t].lc,l,r)
else
iftree[tree[t].rc].l<=l then find(tree[t].rc,l,r)
else
begin
find(tree[t].lc,l,tree[tree[t].lc].r);
find(tree[t].rc,tree[tree[t].rc].l,r);
end;
end;
begin
readln(n);
tot:=0;root:=0;
build(root,1,n);
fori:=1 to n do
begin
read(x);
insert(root,i);
end;
readln(m);
x:=0;
fori:=1 to m do
begin
readln(a,b);
ans:=0;
find(root,a,b);
writeln(ans*3.14:0:2);{<依照样例,所以‘:0’了>}
insert(root,(a+b)div 2);{<插入0>}
end;
end.