## bzoj 1878 SDOI2009树状数组 离线操作

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

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

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
for i:=1 to n do
begin
if tot<a[i] then tot:=a[i];
end;

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;

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

begin
while x>0 do
begin
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]);
ll:=l[i];
end;
qs1(1,m);
for i:=1 to m do writeln(ans[i]);
end;

begin
init;
main;
end.

posted on 2013-12-08 21:01  BLADEVIL  阅读(319)  评论(0编辑  收藏  举报