[BZOJ1818] [Cqoi2010]内部白点

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=1818

题目大意

给定平面上的一些黑点,其它位置都是白点,一个白点如果上下左右都有黑点就会变成黑点,求最终会有多少个黑点

题解

就是求交点个数
离散化后,取出所有线段,然后沿任意一个轴朝着一个方向扫,然后把平行于另一个轴的线段用端点记录,扫到一端就在树状数组里+1,另一端-1,树状数组求个区间和贡献答案即可

const
    maxn=200000;
type
    data=array[0..2*maxn,1..3]of longint;
var
    x,y,z:data;
    bit:array[0..maxn]of longint;
    i,j,k:longint;
    n,len,rx,ry,ans:longint;
function min(a,b:longint):longint;
begin
    if a>b then exit(b) else exit(a);
end;

function max(a,b:longint):longint;
begin
    if a<b then exit(b) else exit(a);
end;

procedure sort(var x:data; l,r:longint);
var i,j,a,b:longint;
begin
    i:=l; j:=r; a:=x[(l+r) div 2,1];
    repeat
        while x[i,1]<a do inc(i);
        while a<x[j,1] do dec(j);
        if not(i>j) then
        begin
            b:=x[i,1]; x[i,1]:=x[j,1]; x[j,1]:=b;
            b:=x[i,2]; x[i,2]:=x[j,2]; x[j,2]:=b;
            b:=x[i,3]; x[i,3]:=x[j,3]; x[j,3]:=b;
            inc(i); dec(j);
        end;
    until i>j;
    if l<j then sort(x,l,j);
    if i<r then sort(x,i,r);
end;

procedure update(pos,val:longint);
begin
    while pos<=ry do
        begin
            inc(bit[pos],val);
            inc(pos,pos and (-pos));
        end;
end;

function query(pos:longint):longint;
var sum:longint;
begin
    sum:=0;
    while pos>0 do
        begin
            inc(sum,bit[pos]);
            dec(pos,pos and (-pos));
        end;
    exit(sum);
end;

begin
    readln(n);
    for i:=1 to n do
        readln(z[i,1],z[i,2]);
    for i:=1 to n do
        begin
            x[i,1]:=z[i,1];
            x[i,2]:=i;
        end;
    sort(x,1,n);
    len:=0; x[0,1]:=-100000005;
    for i:=1 to n do
        if x[i,1]<>x[i-1,1]
        then begin inc(len); z[x[i,2],1]:=len; end
        else z[x[i,2],1]:=len;
    ry:=len;
    for i:=1 to n do
        begin
            x[i,1]:=z[i,2];
            x[i,2]:=i;
        end;
    sort(x,1,n);
    len:=0; x[0,1]:=-100000005;
    for i:=1 to n do
        if x[i,1]<>x[i-1,1]
        then begin inc(len); z[x[i,2],2]:=len; end
        else z[x[i,2],2]:=len;
    rx:=len;
    for i:=1 to n do
        begin x[i,1]:=-maxlongint; x[i,2]:=maxlongint; y[i,1]:=-maxlongint; y[i,2]:=maxlongint; end;
    for i:=1 to n do
        begin
            if x[z[i,2],1]=-maxlongint
            then begin x[z[i,2],1]:=z[i,1]; x[z[i,2],2]:=z[i,1]; end
            else begin x[z[i,2],1]:=min(z[i,1],x[z[i,2],1]); x[z[i,2],2]:=max(z[i,1],x[z[i,2],2]); end;
            if y[z[i,1],1]=-maxlongint
            then begin y[z[i,1],1]:=z[i,2]; y[z[i,1],2]:=z[i,2]; end
            else begin y[z[i,1],1]:=min(z[i,2],y[z[i,1],1]); y[z[i,1],2]:=max(z[i,2],y[z[i,1],2]); end;
        end;
    ans:=0; len:=0;
    for i:=1 to ry do
        begin
            inc(len); z[len,1]:=y[i,1]; z[len,2]:=i; z[len,3]:=1;
            inc(len); z[len,1]:=y[i,2]+1; z[len,2]:=i; z[len,3]:=-1;
        end;
    sort(z,1,len); {z[i,1]}
    j:=1;
    for i:=1 to rx do
        begin
            while z[j,1]=i do
                begin
                    update(z[j,2],z[j,3]);
                    inc(j);
                end;
            ans:=ans+query(x[i,2])-query(x[i,1]-1);
        end;
    writeln(ans);
end.

你可能感兴趣的:([BZOJ1818] [Cqoi2010]内部白点)