万能的线段树和非常简单但是和好用的树状数组,早有耳闻,但一直找不到题目练习,只是照着书上的程序打了一遍练练手而已。最近发现POJ和HDU的acm题库资源真的很丰富呃,先练练手复习一下吧
POJ 2352 求点左下区域的点数,因为数据已经按从下往上,从左到右排序,所以可以用统计当前1到x的点数和就是答案,树状数组即可解决。但是因为树状数组不能处理0下标,代码有点小改动
const
maxn=100000;
var
c,level:array[0..1000000] of longint;
i,j,k,n,m,x,y:longint;
function lowbit(i:longint):longint;
begin
exit(i and -i);
end;
procedure add(i,x:longint);
begin
while i<=maxn do
begin
c[i]:=c[i]+x;
i:=i+lowbit(i);
end;
end;
function getsum(i:longint):longint;
begin
getsum:=0;
while i>0 do
begin
getsum:=getsum+c[i];
i:=i-lowbit(i);
end;
end;
begin
readln(n);
for i:=1 to n do
begin
readln(x,y);
add(x+1,1);
inc(level[getsum(x+1)-1]);
end;
for i:=0 to n-1 do
writeln(level[i]);
end.
HDU 1754 没穿衣服的区间最值问题,线段树基础练习
我的代码仅能通过样例,提交显示编译失败,难道Delphi语法差那么多吗?我在FP下用Delphi模式也能编译通过啊……
type
node=record l,r,c:longint; end;
var
tree:array[1..20000] of node;
a:array[1..20000] of longint;
n,m,i,x,y:longint;
maxnum:longint;
c,c1:char;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure build(p,l,r:longint);
begin
tree[p].l:=l;
tree[p].r:=r;
if l=r then
tree[p].c:=a[l]
else begin
build(p*2,l,(l+r) div 2);
build(p*2+1,(l+r) div 2+1,r);
tree[p].c:=max(tree[p*2].c,tree[p*2+1].c);
end;
end;
procedure find(p,l,r:longint);
var
m:longint;
begin
if (l<=tree[p].l)and(tree[p].r<=r) then
maxnum:=max(maxnum,tree[p].c)
else begin
m:=(tree[p].l+tree[p].r) div 2;
if r<=m then
find(p*2,l,r)
else if l>m then
find(p*2+1,l,r)
else begin
find(p*2,l,m);
find(p*2+1,m+1,r);
end;
end;
end;
procedure insert(p:longint);
var
m:longint;
begin
if tree[p].l=tree[p].r then
tree[p].c:=y
else begin
m:=(tree[p].l+tree[p].r) div 2;
if m>=x then
insert(p*2)
else insert(p*2+1);
tree[p].c:=max(tree[p*2].c,tree[p*2+1].c);
end;
end;
begin
while not eof do
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
readln(c,x,y);
if c='Q' then
begin
maxnum:=-1;
find(1,x,y);
writeln(maxnum);
end
else if c='U' then
insert(1);
end;
end;
end.