要AB上側下側分開考慮,否則選到的四元組可能不合法
複習:樹狀數組求逆序對
int tree[NNN];
inline int lowbit(int x){return x&(-x);}
inline void update(int i){
while(i<=tot){
tree[i]+=1;
i+=lowbit(i);
}
}
inline int query(int i){
int res=0;
while(i>0){
res+=tree[i];
i-=lowbit(i);
}
return res;
}
update(x),ans+=i-query(x);
/*OR*/
ans+=i-query(x)-1,update(x);
ACcode
#include<bits/stdc++.h>
#define re register
#define in Read()
using namespace std;
inline int in{
int i=0,f=1;char ch;
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')ch=getchar(),f=-1;
while(isdigit(ch))i=(i<<1)+(i<<3)+ch-48,ch=getchar();
return i*f;
}
const int NNN=1e5+10;
const double eps=1e-7;
const double pi=3.1415;
int n,ans;
struct Point{
double x,y;
Point(){}
Point(double _x,double _y){x=_x,y=_y;}
inline void print(){printf("(%.5lf,%.5lf)\n",x,y);}
friend inline Point operator + (const Point &u,const Point &v){return Point(u.x+v.x,u.y+v.y);}
friend inline Point operator - (const Point &u,const Point &v){return Point(u.x-v.x,u.y-v.y);}
friend inline Point operator * (const Point &u,const double &v){return Point(u.x*v,u.y*v);}
friend inline Point operator / (const Point &u,const double &v){return Point(u.x/v,u.y*v);}
friend inline double operator ^ (const Point &u,const Point &v){return u.x*v.y-u.y*v.x;}
friend inline double operator % (const Point &u,const Point &v){return u.x*v.x+u.y*v.y;}
}A,B,p[NNN];
struct node{
Point p;
int id;
}now[NNN];
int tot;
inline double dis(Point u,Point v){return sqrt((u-v)%(u-v));}
inline double angle(Point u,Point v,Point w){return acos(((u-v)%(w-v))/(dis(u,v)*dis(w,v)));}
inline bool cmp1(const node &u,const node &v){return ((u.p-A)^(v.p-A))<0;}
inline bool cmp2(const node &u,const node &v){return ((u.p-B)^(v.p-B))<0;}
inline bool cmp3(const node &u,const node &v){return ((u.p-A)^(v.p-A))>0;}
inline bool cmp4(const node &u,const node &v){return ((u.p-B)^(v.p-B))>0;}
int tree[NNN];
inline int lowbit(int x){return x&(-x);}
inline void update(int i){
while(i<=tot){
tree[i]+=1;
i+=lowbit(i);
}
}
inline int query(int i){
int res=0;
while(i>0){
res+=tree[i];
i-=lowbit(i);
}
return res;
}
inline void upward(){
memset(tree,0,sizeof(tree));tot=0;
for(re int i=1;i<=n;++i)
if(((B-A)^(p[i]-A))>0)
now[++tot].p=p[i];
sort(now+1,now+tot+1,cmp1);
for(re int i=1;i<=tot;++i)now[i].id=i;
sort(now+1,now+tot+1,cmp2);
for(re int i=1;i<=tot;++i)
update(now[i].id),ans+=i-query(now[i].id);
}
inline void downward(){
memset(tree,0,sizeof(tree));tot=0;
for(re int i=1;i<=n;++i)
if(((B-A)^(p[i]-A))<0)
now[++tot].p=p[i];
sort(now+1,now+tot+1,cmp3);
for(re int i=1;i<=tot;++i)now[i].id=i;
sort(now+1,now+tot+1,cmp4);
for(re int i=1;i<=tot;++i)
update(now[i].id),ans+=i-query(now[i].id);
}
int main(){
n=in;
A.x=(double)in,A.y=(double)in;
B.x=(double)in,B.y=(double)in;
for(re int i=1;i<=n;++i)
p[i].x=(double)in,p[i].y=(double)in;
upward();
downward();
printf("%d\n",ans);
return 0;
}