一个经典的二维数点模型,如果某个人x两个速度都比另一个人y大,显然y是不可能成为winner的。
但这里只考虑两个人x,y在两个属性各有千秋的时候,一定存在正整数S,R使得x,y都有可能成为winner。
这时考虑单调栈中顶端的两个人a和b,以及此时准备加入的人c,很明显当两两无法比较时,可能存在如下情况:
- 当S与R的比值小于一定值时,a总能胜b。
- 当S与R的比值大于一定值时,c总能胜b。
可以看到,当前者的阀值大于后者的阀值时,就不存在任何一组S和R,能使b成为winner了。(注:这里已经将人按照S值排了序)
前者的不等式大概长这样(当a能胜b):
$ \frac{ s_{a} \, s_{b} \, ( r_{a} - r_{b} ) }{ r_{a} \, r_{b} \, ( s_{b} - s_{a} ) } > \frac{ S }{ R } $
后者的不等式大概长这样(当c能胜b):
$ \frac{ s_{c} \, s_{b} \, ( r_{b} - r_{c} ) }{ r_{c} \, r_{b} \, ( s_{c} - s_{b} ) } < \frac{ S }{ R } $
将式子化简后就能判断b有没有win的可能性了。
扫描二维码关注公众号,回复:
2128139 查看本文章
$ \bigodot $ 技巧&套路:
- 单调栈的应用,单调栈剔除的变式。
1 #include <cstdio> 2 #include <set> 3 #include <algorithm> 4 5 typedef long long LL; 6 const int N = 200005; 7 8 struct No { 9 int x, y, id; 10 inline friend bool operator < (No a, No b) { 11 return (a.x == b.x)? (a.y < b.y) : (a.x < b.x); 12 } 13 } p[N]; 14 15 int n, sta[N], top; 16 std::set<No> S; 17 18 inline int Check(No a, No b, No c) { 19 return (LL) a.x * (a.y - b.y) * c.y * (c.x - b.x) > (LL) c.x * (b.y - c.y) * a.y * (b.x - a.x); 20 } 21 22 int main() { 23 scanf("%d", &n); 24 for (int i = 1; i <= n; ++i) { 25 scanf("%d%d", &p[i].x, &p[i].y); 26 p[i].id = i; 27 } 28 std::sort(p + 1, p + 1 + n); 29 30 for (int i = 1; i <= n; ++i) { 31 while (top >= 1 && p[sta[top]].y <= p[i].y) --top; 32 while (top >= 2 && Check(p[sta[top - 1]], p[sta[top]], p[i])) --top; 33 sta[++top] = i; 34 } 35 for (int i = 1; i <= top; ++i) { 36 S.insert(p[sta[i]]); 37 } 38 top = 0; 39 for (int i = 1; i <= n; ++i) { 40 if (S.count(p[i])) sta[++top] = p[i].id; 41 } 42 std::sort(sta + 1, sta + 1 + top); 43 for (int i = 1; i <= top; ++i) { 44 printf("%d ", sta[i]); 45 } 46 47 return 0; 48 }