您的位置:首页 > 其它

bzoj 1878 SDOI2009树状数组 离线操作

2013-12-08 21:01 381 查看
本来想写2120的,结果想起来了这个

我们先对于询问左端点排序,用树状数组存区间字母个数,对于每种字母,

第一次出现的位置记录为1,剩下的记录为0,然后记录下,每种颜色

后面第一个和他相同颜色的位置

然后扫询问,对于一个询问直接输出区间和,然后假设当前询问是

l1,r1,下一询问是,l2,r2,我们把l1到l2区间内的每个位置颜色的后一颜色

赋值成1,然后继续处理下个询问就好了。

/**************************************************************
Problem: 1878
User: BLADEVIL
Language: Pascal
Result: Accepted
Time:3260 ms
Memory:29524 kb
****************************************************************/

//By BLADEVIL
var
n, m                :longint;
a                   :array[0..50010] of longint;
l, r                :array[0..200010] of longint;
other               :array[0..50010] of longint;
last, first         :array[0..1000010] of longint;
num, ans            :array[0..1000010] of longint;
c                   :array[0..3000010] of longint;
tot                 :longint;

procedure swap(var a,b:longint);
var
c                   :longint;
begin
c:=a; a:=b; b:=c;
end;

procedure qs(low,high:longint);
var
i, j, x             :longint;
begin
i:=low; j:=high; x:=l[(i+j) div 2];
while i<j do
begin
while l[i]<x do inc(i);
while l[j]>x do dec(j);
if i<=j then
begin
swap(l[i],l[j]); swap(r[i],r[j]);
swap(num[i],num[j]);
inc(i); dec(j);
end;
end;
if i<high then qs(i,high);
if j>low then qs(low,j);
end;

procedure qs1(low,high:longint);
var
i, j, x             :longint;
begin
i:=low; j:=high; x:=num[(i+j) div 2];
while i<j do
begin
while num[i]<x do inc(i);
while num[j]>x do dec(j);
if i<=j then
begin
swap(l[i],l[j]); swap(r[i],r[j]);
swap(num[i],num[j]); swap(ans[i],ans[j]);
inc(i); dec(j);
end;
end;
if i<high then qs1(i,high);
if j>low then qs1(low,j);
end;

procedure init;
var
i                   :longint;
begin
read(n);
for i:=1 to n do
begin
read(a[i]);
if tot<a[i] then tot:=a[i];
end;

read(m);
for i:=1 to m do read(l[i],r[i]);
for i:=1 to m do num[i]:=i;
qs(1,m);
for i:=1 to n do
if last[a[i]]<>0 then
begin
other[last[a[i]]]:=i;
last[a[i]]:=i;
end else
begin
last[a[i]]:=i;
first[a[i]]:=i;
end;
end;

procedure add(x:longint);
begin
while x<=n do
begin
c[x]:=c[x]+1;
x:=x+(x and (-x));
end;
end;

function ask(x:longint):longint;
begin
ask:=0;
while x>0 do
begin
ask:=ask+c[x];
x:=x-(x and (-x));
end;
end;

procedure main;
var
i, j                :longint;
ll                  :longint;
begin
for i:=1 to tot do if first[i]<>0 then add(first[i]);
ll:=1;
for i:=1 to m do
begin
for j:=ll to l[i]-1 do if other[j]<>0 then add(other[j]);
ans[i]:=ask(r[i])-ask(l[i]-1);
ll:=l[i];
end;
qs1(1,m);
for i:=1 to m do writeln(ans[i]);
end;

begin
init;
main;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: