牛客練習賽60 F 幾何帶師 題解

2021-10-06 22:48:50 字數 3434 閱讀 5930

題目傳送門

題目大意:給出一條線段 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

log⁡n)

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