咕咕咕咕咕.....
給出一些山頂的座標\((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 看...