计蒜客NOIP2017提高组模拟赛(三)day2-直线的交点
简单几何+逆序对
发现当两条直线甲乙与平板的交点在上面甲在较左的位置,那么下面甲在较右的位置就可以相交
然后把上面的位置排下序,下面离散化+树状数组即可
1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 #include<set> 8 #include<queue> 9 #include<vector> 10 #define INF 0x7f7f7f7f 11 #define pii pair<int,int> 12 #define pdd pair<double,double> 13 #define ll long long 14 #define MAXN 15 using namespace std; 16 int n; 17 int K,A,B; 18 namespace solve1 19 { 20 int read(){ 21 int x=0,f=1;char ch=getchar(); 22 while(ch<'0'||ch>'9'){if('-'==ch)f=-1;ch=getchar();} 23 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 24 return x*f; 25 } 26 int dat[100005]; 27 int n,N; 28 int sum(int k){ 29 int ret=0; 30 while(k<=N){ 31 ret+=dat[k]; 32 k+=(k&-k); 33 } 34 return ret; 35 } 36 void add(int k){ 37 while(k>=1){ 38 dat[k]+=1; 39 k-=(k&-k); 40 } 41 } 42 pdd Node(int k1,int a1,int k2,int a2){ 43 double x=1.0*(a2-a1)/(k1-k2); 44 double y=1.0*(k1*a2-k2*a1)/(k1-k2); 45 return make_pair(x,y); 46 } 47 int K,A,B; 48 int k[100005],a[100005]; 49 pdd b[100005]; 50 pair<double,int> c[100005]; 51 int d[100005]; 52 void solve(){ 53 K=::K,A=::A,B=::B; 54 n=::n; 55 for(int i=1;i<=n;i++){ 56 k[i]=read();a[i]=read(); 57 } 58 for(int i=1;i<=n;i++){ 59 b[i]=make_pair(Node(k[i],a[i],K,A).first,Node(k[i],a[i],K,B).first); 60 } 61 sort(b+1,b+n+1); 62 for(int i=1;i<=n;i++){ 63 c[i]=make_pair(b[i].second,i); 64 } 65 sort(c+1,c+n+1); 66 N=0; 67 for(int i=1;i<=n;i++){ 68 if(1==i||c[i].first!=c[i-1].first){ 69 N++; 70 } 71 d[c[i].second]=N; 72 } 73 ll ans=0; 74 for(int i=1;i<=n;i++){ 75 ans+=sum(d[i]); 76 add(d[i]); 77 } 78 printf("%lld\n",ans); 79 } 80 81 } 82 int read(){ 83 int x=0,f=1;char ch=getchar(); 84 while(ch<'0'||ch>'9'){if('-'==ch)f=-1;ch=getchar();} 85 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 86 return x*f; 87 } 88 89 int main() 90 { 91 // freopen("data.in","r",stdin); 92 K=read();A=read();B=read(); 93 n=read(); 94 solve1::solve(); 95 return 0; 96 }