团体程序设计天梯赛 长城
https://pintia.cn/problem-sets/994805046380707840/problems/994805050277216256
从右向左枚举所有的点
假设枚举到i,考虑让哪个点看到i最优
如上图,当ik的斜率大于等于ij的斜率时,对于i点来说j是不需要的
所以对于每个点要维护一个斜率单调递增的栈,每次的栈顶的点就是要能看到当前点的点
#include<cstdio> using namespace std; #define N 100001 int x[N],y[N]; int st[N],top; bool use[N]; bool check(int i,int j,int k) { long long a=1ll*(y[i]-y[k])*(x[j]-x[k]); long long b=1ll*(y[j]-y[k])*(x[i]-x[k]); return a<=b; } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d%d",&x[i],&y[i]); st[top=1]=1; for(int i=2;i<=n;++i) { if(top>=2) { while(top>=2 && check(i,st[top],st[top-1])) top--; use[st[top]]=true; } st[++top]=i; } int m=0; for(int i=2;i<n;++i) if(use[i]) ++m; printf("%d",m); }