贪心+思维
这一题我本来也是可以做的
经过一段时间的思考后我们可以发现,最先撞击的两个无人机一定是相邻的两个无人机
我们可以用一个优先队列维护所有的相邻的两点撞击的时间
然后贪心地取撞击时间小的点,然后更新
这个撞击时间是一个小数,在比较时有精度误差,因为精度误差我一直错
在涉及小数比较的时候,优先考虑是否可以进行ll比较,避免除法,转化为乘法
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int max_n = 1e5+100;
const double inf = 1e18;
int n;
pll ns[max_n];
int lft[max_n],rgt[max_n];
int tot=0;
struct node
{
ll x,v;
int l,r;
node(ll xx,ll vv,int lf,int rr)
{
x=xx;v=vv;l=lf;r=rr;
}
bool operator<(const node& nn)const
{
bool ans;
if (v<=0&&nn.v<=0)ans= l<nn.l;
else if (v<=0)ans= false;
else if (nn.v<=0)ans=true;
else
{
ans=x*nn.v<nn.x*v;
}
return !ans;
}
};
bool used[max_n];
int main()
{
ios::sync_with_stdio(0);
cin>>n;
++tot;
for (int i=1;i<=n;++i)
{
cin>>ns[i].first>>ns[i].second;
}
for (int i=1;i<=n;++i)rgt[i]=i+1;
for (int i=1;i<=n;++i)lft[i]=i-1;
priority_queue<node> que;
for (int i=2;i<=n;++i)que.push(node(ns[i].first-ns[i-1].first,ns[i-1].second-ns[i].second,i-1,i));
while (!que.empty())
{
node nn = que.top();
que.pop();
if (nn.v<=0)break;
int lt = nn.l,rt = nn.r;
if (used[lt]||used[rt])continue;
int L = lft[lt],R = rgt[rt];
used[lt]=used[rt]=1;
if (L!=0&&R!=n+1)
{
que.push(node(ns[R].first-ns[L].first,ns[L].second-ns[R].second,L,R));
}
rgt[L]=R;
lft[R]=L;
}
int ans=0;
for (int i=1;i<=n;++i)
{
if (!used[i])++ans;
}
cout<<ans<<endl;
for (int i=1;i<=n;++i)if (!used[i])cout<<i<<" ";cout<<endl;
}
京公网安备 11010502036488号