您的位置:首页 > 其它

[CodeVS1081]线段树练习2(区间修改+单点询问)

2015-07-25 14:49 441 查看

线段树练习2

题目描述 Description

给你N个数,有两种操作

1:给区间[a,b]的所有数都增加X

2:询问第i个数是什么?

输入描述 Input Description

第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。

输出描述 Output Description

对于每个询问输出一行一个答案

样例输入 Sample Input

3

1

2

3

2

1 2 3 2

2 3

样例输出 Sample Output

5

数据范围及提示 Data Size & Hint

1<=n<=100000

1<=q<=100000

var
w:array[0..400005,1..4]of longint;
x:array[0..100000]of longint;
i,j,k:longint;
n,m:longint;
a,b,c,d:longint;
procedure build(a,l,r:longint);
var mid:longint;
begin
w[a,1]:=l; w[a,2]:=r;
if l=r then begin w[a,3]:=x[l]; exit; end;
mid:=(l+r)div 2;
build(a*2,l,mid);
build(a*2+1,mid+1,r);
end;

procedure update(a,l,r:longint);
var mid:longint;
begin
if (w[a,1]=l)and(w[a,2]=r)
then begin inc(w[a,3],d); exit; end;
mid:=(w[a,1]+w[a,2])div 2;
if r<=mid
then update(a*2,l,r) else
if l>mid
then update(a*2+1,l,r) else
begin
update(a*2,l,mid);
update(a*2+1,mid+1,r);
end;
end;

function query(a,b:longint):longint;
var mid:longint;
begin
if (w[a,1]<>w[a,2])and(w[a,3]<>0) then begin inc(w[a*2,3],w[a,3]); inc(w[a*2+1,3],w[a,3]); w[a,3]:=0; end;
if (w[a,1]=w[a,2])and(w[a,1]=b)
then exit(w[a,3]);
mid:=(w[a,1]+w[a,2])div 2;
if b<=mid
then exit(query(a*2,b))
else exit(query(a*2+1,b));
end;

begin
readln(n);
for i:=1 to n do
readln(x[i]);
build(1,1,n);
readln(m);
for i:=1 to m do
begin
read(a);
if a=1
then begin readln(b,c,d); update(1,b,c); end
else begin readln(b); writeln(query(1,b)); end;
end;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: