Cod sursa(job #9695)

Utilizator andrei_infoMirestean Andrei andrei_info Data 27 ianuarie 2007 16:43:25
Problema Secventa 5 Scor 10
Compilator fpc Status done
Runda Unirea 2007, clasele 11-12 Marime 3.67 kb
// secventa 5 infoarena concurs unirea 2007
type pnod = ^tnod;
     tnod = record
                nr : longword;
                frecv : longint;
                next : pnod;
                end;
     rr =record
                head,last : pnod;
                end;
const max = 1048555;

var a :array[1..1048576] of longword;
    hash : array[1..2,0..max-1] of rr;
    n,l,u: longint;
    rez : int64;

procedure citire;
var i:longint;
begin
assign(input,'secv5.in'); reset(input);
readln(n,l,u);
for i:=1 to n do
        readln(a[i]);
close(input);
end;

function find(x:longword;hh:integer):longint;
var p : pnod;
    list : longint;
begin
list:= x mod max;
p:=hash[hh][list].head;
find:=0;
while p <> nil do
        begin
        if p^.nr = x then
                begin
                find:=p^.frecv;
                exit;
                end;
        p:=p^.next;
        end;
end;

procedure addlist(val : longword; list : longint;hh:integer);
var p:pnod;
begin
new(p); p^.nr:=val; p^.frecv:=1; p^.next:=nil;
if hash[hh][list].head = nil then
        hash[hh][list].head :=p
else    hash[hh][list].last^.next:=p;
hash[hh][list].last:=p;
end;

procedure update(x:longword; y : integer; hh:integer );
var p : pnod;
    list : longint;
begin
list:= x mod max;
if find(x,hh) = 0 then addlist(x,list,hh)
else
        begin
        p:=hash[hh][list].head;
        while p <> nil do
                begin
                if p^.nr = x then
                        begin
                        p^.frecv:=p^.frecv+y;
                        exit;
                        end;
                p:=p^.next;
                end;
        end;

end;


procedure calc;
var i,start,stop1,stop2,nrdis1,nrdis2:longint;
begin
start:=1;
stop1:=1; stop2:=1;
update(a[1],1,1); update(a[1],1,2);
nrdis1:=1; nrdis2:=1;
while (nrdis1 < l) and (stop1 < n) do
        begin
        inc(stop1);
        if find(a[stop1],1) = 0 then inc(nrdis1);
        update(a[stop1],1,1); update(a[stop1],1,2);
        end;
stop2:=stop1; nrdis2:=nrdis1;
while (nrdis2 < u) and (stop2 < n) do
        begin
        inc(stop2);
        if find(a[stop2],2) = 0 then inc(nrdis2);
        update(a[stop2],1,2);
        //if (stop2+1 <=n) and (find(a[stop2],1)<>0) then break;
        end;
while (find(a[stop2+1],2)<>0) do begin inc(stop2); update(a[stop2],1,2); end;
rez:=stop2-stop1+1;
while (stop1 < n ) do
        begin
        inc(start); update(a[start-1],-1,1); update(a[start-1],-1,2);
        if find(a[start-1],1) = 0 then
                begin
                dec(nrdis1);
                while (nrdis1 < l) and (stop1 < n) do
                        begin
                        inc(stop1);
                        if find(a[stop1],1) = 0 then inc(nrdis1);
                        update(a[stop1],1,1);
                        end;
                end;
        if find(a[start-1],2) = 0 then
                begin
                dec(nrdis2);
                while (nrdis2 < u) and (stop2 < n) do
                        begin
                        inc(stop2);
                        if find(a[stop2],2) = 0 then inc(nrdis2);
                        update(a[stop2],1,2);
                        //if (stop2+1 <= n) and (find(a[stop2],2)<>0) then break;
                        end;
                while (stop2+1 <=n) and (find(a[stop2+1],2)<>0) do begin inc(stop2); update(a[stop2],1,2); end;
                end;
        if nrdis1 >=l then     rez:=rez+ stop2-stop1+1;
        end;
end;


procedure afis;
begin
assign(output,'secv5.out'); rewrite(output);
writeln(rez);
close(output);
end;

begin
citire;
calc;
afis;
end.