题目描述
给出n个直线,求有多少个能够在某个时刻最高。
很明显是一个单调栈的题目……不应该评到紫的。
思路
这道题本意显然不是让你写平方暴力的……但是这个题的的数据过于水了,很多有一些问题的代码都能通过。据我旁边的同学说,他把大部分题解测了一下,发现有很多问题。
我们按照距离从大到小排序,挨个入栈,显然距离和速度都比栈顶小的没有用了。
其次我们看当前栈顶元素超过栈中第二个元素的时间。
如果说当前要插入的这个元素和栈顶相遇(或者理解为超过栈顶)要早于这个时间,那么可以发现栈顶元素是永无出头之日的,可以出栈。
我们可以写分数来避免精度问题(当然好像不写问题也不大)
还要注意特判掉两个元素完全相同,这个时候我们把刚才的元素再入栈就行了。
有些细节可以看代码。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
struct frac{//分数
int x,y;
void yf(){
if(x==0||y==0) return;
int p=__gcd(x,y);
x/=p;y/=p;
}
frac(int a,int b){x=a;y=b;yf();}
frac(){x=0;y=1;}
bool operator<(const frac &b)const{
return x*b.y<y*b.x;
}
};
struct node{
int id,x,y;
frac t;
bool operator<(const node &b)const{
if(x==b.x) return y<b.y;
return x>b.x;
}
};
node a[1000005];
deque<node> v;
signed main(){
ios::sync_with_stdio(0);
cin>>n;
for(int i=0;i<n;i++){cin>>a[i].x;a[i].id=i;}
for(int i=0;i<n;i++){cin>>a[i].y;}
sort(a,a+n);
a[0].t=frac(0,1);
v.push_back(a[0]);
for(int i=1;i<n;i++){
if(!v.empty()&&a[i].x==v.back().x&&a[i].y==v.back().y){//判掉完全相同
v.push_back((node){a[i].id,a[i].x,a[i].y,v.back().t});
continue;
}
if(!v.empty()&&a[i].y<=v.back().y) continue;//判掉打不过
while(!v.empty()&&frac(v.back().x-a[i].x,a[i].y-v.back().y)<v.back().t){//把永无出头之日的栈顶删掉
v.pop_back();
}
v.push_back((node){a[i].id,a[i].x,a[i].y,frac(v.back().x-a[i].x,a[i].y-v.back().y)});//入栈,记录下与栈顶的元素相遇时间用于比较
}
cout<<v.size()<<endl;
vector<int> ans;
while(!v.empty()){
ans.push_back(v.front().id+1);
v.pop_front();
}
sort(ans.begin(),ans.end());
for(int i=0;i<ans.size();i++) cout<<ans[i]<<' ';
return 0;
}
最后一次更新于2021-10-20
0 条评论