现在的位置: 首页 > 综合 > 正文

bzoj2441

2018年01月15日 ⁄ 综合 ⁄ 共 3247字 ⁄ 字号 评论关闭

小W的问题

【问题描述】

有一天,小W找了一个笛卡尔坐标系,并在上面选取了N个整点。他发现通过这些整点能够画出很多个“W”出来。具体来说,对于五个不同的点(x1, y1), (x2, y2), (x3, y3), (x4, y4), (x5, y5),如果满足:

·x1 < x2 < x3 < x4 < x5

·y1 > y3 > y2

·y5 > y3 > y4

则称它们构成一个“W”形。

现在,小W想统计“W”形的个数,也就是满足上面条件的五元点组个数。你能帮助他吗?

Input

    第一行包含一个整数N,表示点的个数。

下面N行每行两个整数,第i+1行为(xi, yi),表示第i个点的坐标。

Output

仅包含一行,为“W”形个数模1 000 000 007的值

这道题我一开始不会做……感谢某神牛的讲解

顺带一提,没有重点

统计的形状十分蛋疼……必须严格是w形

需要把一个点当做研究对象,显然我们选取中间这个点

因为这个点左边和右边互不影响,方案数乘起来即可

问题转换成了统计312(就是指最左边最高,中间最低,最右边中间高)这种类型的数目,并把它存到2的位置

这个似乎不太好统计……所以采用容斥

显然,统计312+213也就是v形两边哪边高都行非常简单……排序后树状数组即可

那么如何求出312……?算出213即可

213似乎也不好求……

但可以发现,研究对象变成了最高的点,另外两个点在同一象限

那么我们可以很简单的算出123+213=([3左下角下的点数]-1)*[3左下角下的点数]/2

然后再减去123……

显然,123非常好求,排序后树状数组即可

细节比较多……认真思考后再开始写

program bzoj2441;
const
    maxn=1000000007;
var
	all,n,i,j,k:longint;
    new,tree,dl,ans,x,y,u,d,c,o:array [0..200001] of longint;

function lowbit (x:longint):longint;inline;
begin
    exit(x xor (x and (x-1)));
end;

procedure insert (p,x:longint);inline;
begin
    if x=0 then exit;
    while x<=n do
        begin
            tree[x]:=(tree[x]+p) mod maxn;
            x:=x+lowbit(x);
        end;
end;

function qsum (x:longint):longint;inline;
var
    ans:longint=0;
begin
    while x>0 do
        begin
            ans:=(ans+tree[x]) mod maxn;
            x:=x-lowbit(x);
        end;
    exit(ans);
end;

procedure swap (var a,b:longint);inline;
begin
    if a=b then exit;
    a:=a xor b;
    b:=a xor b;
    a:=a xor b;
end;

procedure qsort (s,e:longint);
var
    i,j,k:longint;
begin
    if s>=e then exit;
    i:=s;
    j:=e;
    k:=new[(s+e) div 2];
    while i<=j do
        begin
            while new[i]<k do inc(i);
            while new[j]>k do dec(j);
            if i>j then break;
            swap(new[i],new[j]);
            inc(i);
            dec(j);
        end;
    qsort(s,j);
    qsort(i,e);
end;

function convert (x:longint):longint;inline;
var
    s,e,mid:longint;
begin
    s:=1;
    e:=all;
    while s<>e do
        begin
            mid:=(s+e) div 2;
            if new[mid]<x then s:=mid+1
                                else e:=mid;
        end;
    exit(s);
end;

procedure calc;

    procedure qsort (s,e:longint);
    var
        i,j,k:longint;
    begin
        if s>=e then exit;
        i:=s;
        j:=e;
        k:=dl[(s+e) div 2];
        while i<=j do
            begin
                while (x[dl[i]]<x[k])or((x[dl[i]]=x[k])and(y[dl[i]]<y[k])) do inc(i);
                while (x[dl[j]]>x[k])or((x[dl[j]]=x[k])and(y[dl[j]]>y[k])) do dec(j);
                if i>j then break;
                swap(dl[i],dl[j]);
                inc(i);
                dec(j);
            end;
        qsort(s,j);
        qsort(i,e);
    end;

begin
    qsort(1,n);
    fillchar(tree,sizeof(tree),0);
    i:=1;
    while i<=n do
        begin
            k:=i;
            while (i<=n)and(x[dl[i]]=x[dl[k]]) do
                begin
                    d[dl[i]]:=qsum(y[dl[i]]);
                    if d[dl[i]]>0 then d[dl[i]]:=int64(d[dl[i]]-1)*d[dl[i]] div 2 mod maxn;
                    inc(i);
                end;
            for j:=k to i-1 do
                insert(1,y[dl[j]]);
        end;
    fillchar(tree,sizeof(tree),0);
    for i:=1 to n do
        begin
            c[dl[i]]:=qsum(y[dl[i]]);
            insert(1,y[dl[i]]);
        end;
    fillchar(tree,sizeof(tree),0);
    o:=c;
    i:=1;
    while i<=n do
        begin
            k:=i;
            while (i<=n)and(x[dl[i]]=x[dl[k]]) do
                begin
                    c[dl[i]]:=qsum(y[dl[i]]);
                    inc(i);
                end;
            for j:=k to i-1 do
                insert(o[dl[j]],y[dl[j]]);
        end;
    fillchar(tree,sizeof(tree),0);
    i:=1;
    while i<=n do
        begin
            k:=i;
            while (i<=n)and(x[dl[i]]=x[dl[k]]) do
                begin
                    u[dl[i]]:=qsum(all)-qsum(y[dl[i]]);
                    inc(i);
                end;
            for j:=k to i-1 do
                insert(1,y[dl[j]]);
        end;
    fillchar(tree,sizeof(tree),0);
    o:=u;
    i:=1;
    while i<=n do
        begin
            k:=i;
            while (i<=n)and(x[dl[i]]=x[dl[k]]) do
                begin
                    u[dl[i]]:=qsum(y[dl[i]]-1);
                    inc(i);
                end;
            for j:=k to i-1 do
                insert(o[dl[j]],y[dl[j]]);
        end;
    for i:=1 to n do
        ans[dl[i]]:=ans[dl[i]]*int64(u[dl[i]]-(d[dl[i]]-c[dl[i]])) mod maxn;
end;

begin
    read(n);
    for i:=1 to n do
        read(x[i],y[i]);
    for i:=1 to n do
        new[i]:=y[i];
    qsort(1,n);
    i:=1;
    while i<=n do
        begin
            inc(all);
            new[all]:=new[i];
            while (i<=n)and(new[i]=new[all]) do inc(i);
        end;
    for i:=1 to n do
        y[i]:=convert(y[i]);
    for i:=1 to n do 
        ans[i]:=1;
    for i:=1 to n do
        dl[i]:=i;
    calc;
    for i:=1 to n do
        x[i]:=-x[i];
    calc;
    k:=0;
    for i:=1 to n do
        k:=(k+ans[i]) mod maxn;
    writeln((k+maxn) mod maxn);
end.
【上篇】
【下篇】

抱歉!评论已关闭.