原题链接
思路:
前几天刚做了可见线段的
思考方式是差不多的,考虑什么时候必须加一个烽火台。
A点看不见C点,所以在B必须要放一个烽火台。
然后再类似凸包,用一个单调栈维护
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll>PLL;
typedef pair<int,int>PII;
#define I_int ll
#define modl 19260817*19890604-19491001
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
#define read read()
char F[200];
inline void out(I_int x) {
if (x == 0) return (void) (putchar('0'));
I_int tmp = x > 0 ? x : -x;
if (x < 0) putchar('-');
int cnt = 0;
while (tmp > 0) {
F[cnt++] = tmp % 10 + '0';
tmp /= 10;
}
while (cnt > 0) putchar(F[--cnt]);
//cout<<" ";
}
const int maxn=1e5+100;
struct node{
ll x,y;
int id;
}line[maxn],stk[maxn];
ll n,top;
ll cul(node p1,node p2,node p0)//计算叉积,p1,p2,p0都为点
{
ll x1,y1,x2,y2;
x1=p1.x-p0.x;
y1=p1.y-p0.y;
x2=p2.x-p0.x;
y2=p2.y-p0.y;
return x1*y2-x2*y1;
}
int vis[maxn];
int main(){
n=read;
for(int i=1;i<=n;i++){
cin>>line[i].x>>line[i].y;
line[i].id=i;
}
for(int i=1;i<=n;i++){
while(top>=2&&cul(stk[top-1],stk[top],line[i])<=0) top--;
if(stk[top].id!=1) vis[stk[top].id]=1;
stk[++top]=line[i];
}
int cnt=0;
for(int i=1;i<=n;i++)
if(vis[i]) cnt++;
cout<<cnt<<endl;
return 0;
}