1. 程式人生 > 實用技巧 >2020杭電多校第一場1009 Leading Robots 單調棧

2020杭電多校第一場1009 Leading Robots 單調棧

http://acm.hdu.edu.cn/showproblem.php?pid=6759

題意:

有n個機器人,每個機器人有一個初始位置和加速度,同時向右移動,跑道很長,沒有終點。在某個特定時間,如果機器人是最右邊且唯一的,那麼它就是當時的領先機器人。問:領先機器人的數量。

題解:

參考部落格:https://blog.csdn.net/qq_44828887/article/details/107499606

加速度從小到排序,相同加速度位置從小到大排序,後面的機器人肯定可以超過前面的機器人(同加速度,同位置除外);

維護一個棧,棧中的機器人是領先機器人,當前入棧的機器人肯定可以超過棧中的機器人。

當後面(正要入棧的)機器人的位置大於等於前面(棧中)機器人的位置時,位置大的肯定會超過前一個(棧中)機器人,前一個機器人不可能是領先機器人,位置相等且加速度相同的機器人並行也不可能是領先機器人,所以出棧;

當棧中機器人>1時,如果棧頂前兩個機器人相遇的時間 大於 棧頂機器人和正要入棧的機器人相遇的時間,棧頂機器人出棧;

最後判斷棧中是否有並行機器人,有就減掉。

程式碼:

#include <bits/stdc++.h>
using namespace std;
const int MAXN=5e4+5;
const int SIZE=5e4+5;
const long long mod=998244353;
typedef long long ll;
//typedef __int128 LL;
const int inf=0x3f3f3f3f;
const long long
INF=0x3f3f3f3f3f3f3f3f; int st[MAXN]; struct node { ll l,a; bool operator<(const node &Node)const{ if(a==Node.a)return l<Node.l; return a<Node.a; } }; node p[MAXN]; map<node,int>mp; bool check(node x,node y,node z) { return (y.l-z.l)*(y.a-x.a)-(x.l-y.l)*(z.a-y.a)<=0
; } int main() { int t; scanf("%d",&t); while(t--) { mp.clear(); int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lld%lld",&p[i].l,&p[i].a); mp[p[i]]++; } sort(p+1,p+1+n); int top=0; for(int i=1;i<=n;i++) { while((top>0&&p[i].l>=p[st[top]].l)||(top>1&&check(p[st[top-1]],p[st[top]],p[i])))--top; st[++top]=i; } int ans=top; for(int i=1;i<=top;i++) { if(mp[p[st[i]]]>1)ans--; } printf("%d\n",ans); } return 0; }
View Code