卿学姐终于来到了魔王的城堡,城堡修建的十分壮观。
即使心中放不下公主,卿学姐还是忍不住驻足观赏这宏伟的建筑。
卿学姐注意到城堡的墙上有若干直线状的花纹。
可以将墙看做一个平面,卿学姐想知道有多少种方式任取两个直线,使得这两个直线的交点的横坐标$x$满足:$u\le x \le v$。
第一行三个整数$N,u,v$,标明直线有$N$条。
接下来有$N$行,每行两个整数$k,b$,表示这条直线是$y=kx+b$
$1\le N \le 200000$
$0\le \left | k \right | \le 1000000000$
$0\le \left |b \right | \le 1000000000$
$0\le \left |u \right | \le 1000000000$
$0\le \left |v \right | \le 1000000000$
输入保证$u \le v$,保证没有两条直线是一样的
输出一个整数,代表选择的方法数。
上图是样例的解释,交点是A,B,C
题解:在两条直线x=u和x=v之间有交点可以等同于f(u)<g(u)&f(v)>g(v),因此这个问题就转化为了一个逆序对问题,只要求出逆序对数量即可
代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstdlib> using namespace std; typedef struct num { long long k1; long long b1; long long y1; bool operator <(const num &other)const { if(y1==other.y1) return k1>other.k1; else return y1<other.y1; } }Num1; Num1 lin[400000]; long long t[400000]; long long sum=0; void merge(long long* a,long long l, long long mid, long long r ) { long long p = 0; long long i = l, j = mid + 1; while(i <= mid&& j <= r) { if(a[i] >= a[j]) { t[p++] = a[j++]; sum =sum + mid - i + 1; } else { t[p++] = a[i++]; } } while(i <= mid) t[p++] = a[i++]; while(j <= r) t[p++] = a[j++]; for(i = 0; i < p; i++) { a[l + i] = t[i]; } } void mergesort(long long*a,long long l ,long long r) { if(l < r) { long long mid = (r - l) / 2 + l; mergesort(a,l , mid); mergesort(a,mid + 1 , r); merge(a,l, mid , r); } } int main() { long long N,u,v; long long y2[200001]; scanf("%lld %lld %lld",&N,&u,&v); for(long long i=0;i<N;i++) { scanf("%lld %lld",&lin[i].k1,&lin[i].b1); lin[i].y1=lin[i].k1*u+lin[i].b1; } sort(&lin[0],&lin[N]); for(long long i = 0;i<N;i++) { y2[i]=lin[i].k1*v+lin[i].b1; } mergesort(y2,0,N-1); printf("%lld",sum); return 0; }