团体程序设计天梯赛 长城

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);
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/13666736.html