Codevs 2981 查字典 1

题目描述 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值