万能的线段树和非常简单但是和好用的树状数组,早有耳闻,但一直找不到题目练习,只是照着书上的程序打了一遍练练手而已。最近发现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.