省選測試9

2022-06-26 13:57:14 字數 3797 閱讀 1289

​ 咕咕咕咕咕.....

​ 給出一些山頂的座標\((x_i,y_i)\), 每在乙個山頂, 你將會找到當前能夠看到的最高的山頂(乙個山頂\(p\)能看到另乙個山頂\(q\)當且僅當它們的連線\(p,q\)只與\(p,q\)相交).

​ 爬到最高的山頂後你會停下來, 要計算對於每個山頂, 如果從這裡開始爬, 會爬過幾個山頂.(重複經過算多次). \(y\)座標相同的情況下選\(x\)比較大的作為最高山頂.

​ \(n <= 5e5, 0 <= x_i, y_i<= 1e6\)

​ 單調棧.

​ 首先我們需要知道在乙個山頂可以看到最高的山頂是**, 直接單調棧就好了.

​ 設\(to[i]\)為\(i\)這個點為可以看到的最高的點. 我們在往\(to[i]\)走的時候, 可能會經過\(j\)點, \(to[j].y > to[i].y\), 這時候我們需要改變要去的點, 變為\(to[j]\), 也就是說我們需要在\(j\)的答案上再加上一些\(i\)到\(j\)經過的點才能得到\(i\)的答案.

​ 很容易發現這樣的關係可以構成一顆樹, 我們如果可以找到每個點應該從那些點的答案更新過來, 那麼我們就可以建出一顆樹, 在樹上求出每個點到根的距離就是最終答案了.

​ 設\(pre[i]\)是\(i\)前面第乙個\(to[pre[i]].y > to[i].y\)的位置, \(nxt[i]\)是\(i\)後面第乙個\(to[nxt[i]].y > to[i].y\)的位置. 如果\(to[i] > i\), 那麼我們要走到\(nxt[i]\), 如果\(to[i] < i\), 那麼我們要走到\(pre[i]\).

​ 找出每個點的\(pre, nxt\)也用單調棧就可以了.

#include using namespace std;

inline long long read()

const int n = 5e5 + 5;

const double eps = 1e-9;

int n, top;

int to[n], pre[n], nxt[n], sta[n];

struct point

point(double x, double y)

} a[n];

point operator - (const point &a, const point &b)

double cro(point a, point b)

int dcmp(double x)

void get_to()

top = 0; sta[++ top] = n; sta[++ top] = n - 1;

nxt[n] = n; nxt[n - 1] = n;

for(int i = n - 2;i >= 1; i--)

for(int i = 1;i <= n; i++)

}int rt, cnt;

int head[n];

long long ans[n];

struct edge e[n << 1];

void add(int x, int y, int z)

int cmp(int i, int j)

void get_pre_nxt()

top = 0;

for(int i = n;i >= 1; i--)

int max = 0;

for(int i = 1;i <= n; i++)

if(a[i].y >= max) max = a[i].y, rt = i;

for(int i = 1;i <= n; i++)

}void get_ans(int x)

}int main() /*4

0 10

1 52 0

3 610

0 19

1 62 9

3 14 18

5 16

6 67 7

8 18

9 19

*/

​ 小 k 養了 只鴿子,這 只鴿子可以看成平面直角座標系內的 n 個固定的整點。

​ 同時,為了看住這些鴿子,小 k 可以在 m 個給定的點上選擇其中的若干個點安裝監視器。

​ 對於乙隻鴿子,它被監視當且僅當下面三個條件之一成立:

​ 現在小 k 要讓所有鴿子都被監視,請問他最少需要選擇多少個給定的位置設定監視器。

\(2 <= n <= 1e5,3 <= m <= 500\).

​ 凸包.

​ 對於兩個監視器\(a,b\), 我們可以連一條從\(a\)到\(b\)的邊(注意有方向)當且僅當所有鴿子都在它的左邊, 這個用叉積判斷就可以了.

​ 所有監視器都連完邊後, 我們用floyd求最小環就可以得到答案了.

​ 怎麼判斷所有鴿子都在一條線的左邊呢? 我們可以把鴿子的凸包求出來, 只需要判斷離這條直線最近的點是否在直線的左邊就好了.我們可以在凸包上二分斜率來得到這個點.

#include using namespace std;

inline long long read()

const int n = 1e5 + 5, inf = 1e9;

const double eps = 1e-9;

int n, m, topx, tops;

struct point

point(double x, double y)

friend int operator < (const point &a, const point &b)

} a[n], b[n], stax[n], stas[n];

point operator - (const point &a, const point &b)

double cro(point a, point b)

int dcmp(double x)

void convexhall()

stas[++ tops] = a[n]; stas[++ tops] = a[n - 1];

for(int i = n - 2;i >= 1; i--)

}double xl(point a, point b)

int judge(int i, int j)

else if(t1 > 0 && t2 > 0) r = mid - 1;

else l = mid + 1;

}l = 2, r = topx - 1;

while(l <= r)

else if(t1 < 0 && t2 < 0) r = mid - 1;

else l = mid + 1;

}if(dcmp(cro(ans1 - b[i], b[j] - b[i])) >= 0)

else if(dcmp(cro(ans2 - b[i], b[j] - b[i])) <= 0)

else return 0;

}long long ans;

long long f[505][505], d[505][505];

int main()

}for(int i = 1;i <= m; i++) }}

printf("%lld", ans > m ? -1 : ans);

fclose(stdin); fclose(stdout);

return 0;}/*

4 40 0

1 00 1

-1 0

0 11 0

0 -1

-1 0

2 4-1 0

1 0-2 -1

-2 1

2 -1

2 1*/

省選測試9

這個名次已經是倒數了 感覺整場考試不是很在狀態,正解想不到,暴力分也沒有打滿 其實前兩道題仔細推一下還是能想出來的 t1 2 sat 有一段時間沒有打了 優化建圖的方式和之前的某道題挺像的,但是當時那道題沒改 這次算是補了乙個鍋 t2 的資料範圍折半列舉也不難想,實現時注意一下細節就行了 t3 有一...

省選模擬9 題解

直接將 varphi i j 展開為 varphi i varphi j frac 於是可以套用莫比烏斯反演。最終的式子大概是 sum limits f t sum limits sum limits varphi i t varphi j t dis p p 然後我的思路就偏了。為了統計 dis ...

省選測試21

設 f i 為上一次參加的比賽是第 i 場的最大愉悅值 則 f i max f i f j frac a i j 對於隨機的資料,把列舉的範圍卡到 3000 即可 容易發現,如果沒有 a j leq a i 的限制,那麼就是乙個裸的斜率優化 dp 把 f i frac frac 看做 y 把 i 看...