團體程式設計天梯賽 長城
阿新 • • 發佈:2020-09-14
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,intk) { 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); }