小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.