题意:m组询问,求[l,r]中包含了多少种不同的权值
离线+树状数组,还是原来的配方,还是熟悉的呆马...
把询问按l从小到大排序,
i指针从1到n扫,保证每种权值在[i,r]中第一次出现的位置在树状数组中赋为1,其余位置为0
当i与当前询问的l重合时,当前询问的答案为[l,r]的区间和
type
rec=record
l,r,num:longint;
end;
var
n,m,tot,ll :longint;
i,j :longint;
ans :array[0..200010] of longint;
a :array[0..200010] of rec;
first,last :array[0..1000010] of longint;
t :array[0..100010] of longint;
c,next :array[0..50010] of longint;
function lowbit(x:longint):longint;
begin
exit(x and (-x));
end;
procedure sort1(ll,rr:longint);
var
i,j:longint;
x:longint;
y:rec;
begin
i:=ll;j:=rr;
x:=a[(ll+rr) div 2].l;
while (i<=j) do
begin
while (a[i].l<x) do inc(i);
while (a[j].l>x) do dec(j);
if (i<=j) then
begin
y:=a[i];a[i]:=a[j];a[j]:=y;
inc(i);dec(j);
end;
end;
if (i<rr) then sort1(i,rr);
if (j>ll) then sort1(ll,j);
end;
procedure add(x:longint);
begin
while (x<=n) do
begin
inc(t[x]);
inc(x,lowbit(x));
end;
end;
function find(x:longint):longint;
var
ans:longint;
begin
ans:=0;
while (x>0) do
begin
inc(ans,t[x]);
dec(x,lowbit(x));
end;
exit(ans);
end;
begin
read(n);
for i:=1 to n do
begin
read(c[i]);
if (c[i]>tot) then tot:=c[i];
end;
//
read(m);
for i:=1 to m do read(a[i].l,a[i].r);
for i:=1 to m do a[i].num:=i;
sort1(1,m);
for i:=1 to n do
begin
if (last[c[i]]=0) then
begin
last[c[i]]:=i;
first[c[i]]:=i;
end else
begin
next[last[c[i]]]:=i;
last[c[i]]:=i;
end;
end;
//
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 a[i].l-1 do
if next[j]<>0 then add(next[j]);
ans[a[i].num]:=find(a[i].r)-find(a[i].l-1);
ll:=a[i].l;
end;
//
for i:=1 to m do writeln(ans[i]);
end.
——by Eirlys