bzoj 1293 贪心

 

首先我们可以将这道题看成一个数轴,数轴其中的某些点存在一些颜色,我们要选取最短的一段,使这段存

在所有颜色,那么我们使用指针i,j表示在j-i位置中包含的颜色,那么初值是0,0,我们先i++,同时添加i位置

的颜色,直到j-i中存在所有颜色,然后j++,同时删除颜色,直到不存在所有颜色,然后更新答案,重复这过程,

因为i,j只增不减,所以是o(n)的,但是要离散化,还是nlogn的,也算是贪心吧

/**************************************************************
    Problem: 1293
    User: BLADEVIL
    Language: Pascal
    Result: Accepted
    Time:3968 ms
    Memory:23664 kb
****************************************************************/
 
//By BLADEVIL
var
    n, k                            :longint;
    a, c, size                      :array[0..1000010] of longint;
    flag                            :array[0..100] of longint;
    tot                             :longint;
    l                               :longint;
    pre, other                      :array[0..1000010] of longint;
    last                            :array[0..1000010] of longint;
     
function min(a,b:longint):longint;
begin
    if a>b then min:=b else min:=a;
end;
     
procedure swap(var a,b:longint);
var
    c                               :longint;
begin
    c:=a; a:=b; b:=c;
end;
 
procedure connect(x,y:longint);
begin
    inc(l);
    pre[l]:=last[x];
    last[x]:=l;
    other[l]:=y;
end;
     
procedure qs(low,high:longint);
var
    i, j                            :longint;
    xx                              :longint;
begin
    i:=low; j:=high; xx:=a[(i+j) div 2];
    while i<j do
    begin
        while a[i]<xx do inc(i);
        while a[j]>xx do dec(j);
        if i<=j then
        begin
            swap(a[i],a[j]);
            swap(c[i],c[j]);
            inc(i); dec(j);
        end;
    end;
    if i<high then qs(i,high);
    if j>low then qs(low,j);
end;
     
procedure init;
var
    i, j                            :longint;
    x, y                            :longint;
     
begin
    read(n,k);
    for i:=1 to k do
    begin
        read(x);
        for j:=1 to x do
        begin
            read(y);
            inc(tot);
            a[tot]:=y;
            c[tot]:=i;
        end;
    end;
    qs(1,tot);
end;
     
procedure main;
var
    i, j                            :longint;
    cur                             :longint;
    ans, sum                        :longint;
    q, p                            :longint;
     
begin
    tot:=0;
    cur:=-1;
    for i:=1 to n do
    begin
        if a[i]<>cur then
        begin
            inc(tot);
            size[tot]:=a[i];
            cur:=a[i];
            connect(tot,c[i]);
        end else
        begin
            connect(tot,c[i]);
        end;
    end;
    ans:=maxlongint;
    i:=0; j:=0; sum:=0;
    fillchar(flag,sizeof(flag),0);
    while i<tot do
    begin
        while sum<k do
        begin
            inc(i);
            q:=last[i];
            while q<>0 do
            begin
                p:=other[q];
                if flag[p]=0 then
                begin
                    flag[p]:=1;
                    inc(sum);
                end else inc(flag[p]);
                q:=pre[q];
            end;
            if i>tot then break;
        end;
        if i>tot then break;
        while sum>=k do
        begin
            inc(j);
            q:=last[j];
            while q<>0 do
            begin
                p:=other[q];
                dec(flag[p]);
                if flag[p]=0 then dec(sum);
                q:=pre[q];
            end;
            if j>tot then break;
        end;
        ans:=min(ans,size[i]-size[j]);
    end;
    writeln(ans);
end;
     
begin
    init;
    main;
end.

 

posted on 2013-12-16 10:17  BLADEVIL  阅读(348)  评论(0编辑  收藏  举报