题目描述 Description
小明喜欢查字典。
一天,他从电脑上下载了一种字典。这种字典的查询方式十分奇怪:首先将字典读入内存,保存在本地的字典消失;在内存中给每个词分布一个内存地址,然后按地址查询。然而这个字典的内存又很奇怪:每隔一定时间自动变化。小明研究了很久才知道了变化规律。现在,他给你这个变化规律,让你输出一个内存区间内的单词个数。
输入描述 Input Description
第一行 n 表示有n个单词
接下来n行 有 Mi Xi 分别表示单词的内存地址和这个单词。
接下来 m 表示变化规律的种数
接下来m行 三个值 S1 S2 S3 表示 S1到S2的内存范围内每个单词后移S3位。(不会与之前单词有冲突,如果S3为负则前移,S2可能小于S1)
接下来 k 表示小明要问的内存区间个数
接下来k行 两个值 A1 A2 表示要查询的区间【A1,A2】之间的单词个数。
输出描述 Output Description
k行 每行一个值,表示之间的单词个数;
样例输入 Sample Input
2
12343 string
7777 callofduty
1
7666 333333 1
2
1000 99999
7776 7778
样例输出 Sample Output
2
1
数据范围及提示 Data Size & Hint
0<=n,m,k<=10000
内存地址不超过10^6;单词字符数不超过50;
其实就是线段树,但数据奇弱。
分析
该题即为修改值和区间和查询。
刚刚接触了树状数组代码粗糙,见谅。
代码如下
program p2981;
var n,m,x,s1,s2,s3,l,r,i,j:longint;
a:array[1..1000000] of longint;
c:array[1..1000000] of longint;
function lowbit(i:longint):longint;
begin
exit(i and (-i));
end;
procedure modify(num,i:longint);
begin
while i<=1000000 do
begin
c[i]:=c[i]+num;
i:=i+lowbit(i);
end;
end;
function getsum(x:longint):longint;
begin
getsum:=0;
while x>0 do
begin
getsum:=getsum+c[x];
x:=x-lowbit(x);
end;
exit(getsum);
end;
begin
assign(input,'D:/input/codevs/p2981.txt');
reset(input);
assign(output,'D:/output/codevs/p2981.txt');
rewrite(output);
readln(n);
for i:=1 to n do
begin
readln(x);
a[x]:=1;
modify(1,x);
end;
readln(m);
for i:=1 to m do
begin
readln(s1,s2,s3);
for j:=s2 downto s1 do
begin
modify(-a[i],j);
modify(a[i],j+s3);
end;
end;
readln(m);
for i:=1 to m do
begin
readln(l,r);
writeln(getsum(r)-getsum(l-1));
end;
close(input);
close(output);
end.
评测结果
运行结果
测试点#dict1.in 结果:AC 内存使用量: 1520kB 时间使用量: 84ms
测试点#dict2.in 结果:AC 内存使用量: 368kB 时间使用量: 1ms
测试点#dict3.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms