題目傳送門
題目大意:給出一條線段 pqpq
pq以及 n
nn 個點,問從這 n
nn 個點裡面選出兩個點,這兩個點所在直線穿過 pqpq
pq的方案數。
考慮在 pqpq
pq同側的兩點 a,b
a,ba,
b,假如 abab
ab穿過 pqpq
pq,那麼一定有 b
bb 在 δpq
a\delta pqa
δpqa
內或 a
aa 在 δpq
b\delta pqb
δpqb
內。不妨設 a
aa 在 δpq
b\delta pqb
δpqb
內,那麼一定滿足 a,b
a,ba,
b 間一定滿足 ∠bp
q>∠a
pq,∠
bq
p>∠a
qp
\angle bpq>\angle apq,\angle bqp>\angle aqp
∠bpq
>∠a
pq,∠
bqp>∠a
qp,這個您隨手畫兩條線段就能明白。
然後這個東西是個二維偏序問題,可以在 o(n
logn)
o(n\log n)
o(nlogn)
的時間內求出。
假如 a,b
a,ba,
b 在 pqpq
pq異側,那麼就滿足 ∠bp
q+∠a
pq
<
180°
\angle bpq +\angle apq<180\degree
∠bpq+∠
apq<18
0°和 ∠bq
p+∠a
qp
<
180°
\angle bqp +\angle aqp<180\degree
∠bqp+∠
aqp<18
0°。移一下項,就是 ∠ap
q<
180°−∠
bp
q\angle apq<180\degree-\angle bpq
∠apq
<18
0°−∠
bpq 和 ∠aq
p<
180°−∠
bq
p\angle aqp<180\degree -\angle bqp
∠aqp
<18
0°−∠
bqp,依然是個二維偏序問題。
再說點細節,判斷乙個點在 pqpq
pq哪一側時,用兩向量的叉積模長的正負性來判斷(具體參考這裡),求角度時,用三條邊長度和餘弦定理求出該角的 cos
\cos
cos,再用c++裡的 aco
sacos
acos
函式求出其角度。
至於求二維偏序問題時,用的是簡單的樹狀陣列的做法。
**如下:
#include
#include
#include
#include
using
namespace std;
#define maxn 400010
#define ll long long
int n;
struct point;}
point operator-(
const point &b);}
ll chaji
(const point &b)
}p,q,a[maxn]
;double s[maxn][2
],b[maxn]
;double
dis(point x,point y)
ll tree[maxn]
;void
add(
int x)
ll sum
(int x)
double
getangle
(double x,
double y,
double z)
struct par
bool
operator
<
(const par b)
const
}id[maxn]
;int t,tt;
ll work1
(point &a,point &b)
//同側
sort
(b+1
,b+tt+1)
;for
(int i=
1;i<=t;i++
)//求二維偏序前的離散化
id[i]
.x=lower_bound
(b+1
,b+tt+
1,s[i][0
])-b,id[i]
.y=lower_bound
(b+1
,b+tt+
1,s[i][1
])-b;sort
(id+
1,id+t+1)
;for
(int i=
1;i<=t;i++
)re+
=sum
(id[i]
.y),
add(id[i]
.y);
return re;
}const
double pi=
acos(-
1);ll work2
(point &a,point &b)
//異側
sort
(b+1
,b+tt+1)
;for
(int i=
1;i<=n;i++
) id[i]
.x=lower_bound
(b+1
,b+tt+
1,s[i][0
])-b,id[i]
.y=lower_bound
(b+1
,b+tt+
1,s[i][1
])-b,id[i]
.type=
((b-a)
.chaji
(a[i]
-a)>0)
;sort
(id+
1,id+n+1)
;for
(int i=
1;i<=n;i++)if
(id[i]
.type)re+
=sum
(id[i]
.y-1);
else
add(id[i]
.y);
return re;
}int
main()
牛客練習賽60補題
思路 考慮位運算 的特性 只有兩者都為1才會對答案有貢獻 且 對答案貢獻的值為 1 k 其中k是當前1所在二進位制下的位數 所以考慮預處理每乙個位的1出現的次數 其中對每一位都會遍歷n n次 所以每一位對答案的貢獻就是 a i a i 1 i a i 為當前位置1的個數 include using ...
牛客練習賽22題解
簡單瞎搞題 不會用bitset,所以沒做出來。實際上還是比較簡單的。include using namespace std bitset 1000005 dp 2 int main cout 2 count 簡單資料結構1 這裡要運用拓展尤拉定理。ab modp ab p b p p 0 modp ...
題解 牛客練習賽51
字首a的數量,字尾c的數量,遇到b就計算一次答案。includeusing namespace std typedef long long ll const int n 1e5 100 char s n int cnt n int main int tmp 0 for int i 1 i n i p...