日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU多校1 - 6759 Leading Robots(单调栈)

發(fā)布時間:2024/4/11 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU多校1 - 6759 Leading Robots(单调栈) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:n 個機器人在數(shù)軸上賽跑,給出每個機器人的起點和加速度,初始速度都為 0 ,問有多少個機器人在賽跑的過程中可以成為最前面的一個

題目分析:又是被zx學長秒掉的一道題,感謝zx學長的耐心講解

首先根據(jù)高中物理知識,根據(jù)已知條件,可以得到位移與時間的方程?,y 代表位移,x 代表時間,b 代表初始位置,k 代表加速度

因為都是拋物線,求交點非常的麻煩,因為我們只需要求交點的相對位置,所以可以將方程轉(zhuǎn)換為位移與時間的平方的方程:,這樣并不會影響交點的相對位置,同時將每一個位移曲線都轉(zhuǎn)換為一條直線表示了

那么如何將機器人成為最前面的一個體現(xiàn)出來呢?將 n 條直線對應到平面直角坐標系中,將 x 軸從 [ 0 , inf ) 劃分為無數(shù)個點,對于每個 x 而言,對應位置最上面的那條直線所代表的機器人,就是在 x 時刻最領先的機器人,所以我們只需要統(tǒng)計有多少條直線成為過最上面的直線就好了

按照斜率排序,就可以發(fā)現(xiàn)相鄰的三條直線會出現(xiàn)下面兩種情況:

我們將直線 i - 1 與直線 i 的交點記為 ( x1 , y1 ) ,將直線 i 與直線 i + 1 的交點記為 ( x2 , y2 ) ,發(fā)現(xiàn)當 x1 < x2 時,直線 i 所代表的機器人才有可能在最上面,而當 x1 >= x2 時,直線 i 完全被直線 i - 1 和直線 i + 1 所擋住,也就無法在最上面了

到此為止,我們就可以利用單調(diào)棧來實現(xiàn)上述模擬了,棧內(nèi)維護的是都可以在最上面的直線,對于新遍歷到的直線 i ,因為我們已經(jīng)按照斜率遞增了,顯然單調(diào)棧內(nèi)所有初始位置 b 小于當前直線的直線都是不符合條件的,如下圖所示:

顯然在上圖中,st [ top ] 所代表的直線完全被第 i 條直線所覆蓋

還有就是對于棧中的元素,將 st[ top - 1 ] , st[ top ] 和 i 這三條直線分別對應上文中的 i - 1 , i , i + 1 三條直線來比較交點的位置亦可以判斷合理性

最后有個坑點,就是如果有兩個機器人,起點和加速度都是相同的話,那么這兩個機器人是不會對答案提供貢獻的,這個可以用 map 判斷一下

代碼:
?

#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<unordered_map> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=5e4+100;const double eps=1e-8;const double pi = acos(-1.0);int sgn(double x){if(fabs(x) < eps)return 0;if(x < 0)return -1;else return 1; }struct Line {LL k,b;bool operator<(const Line& t)const{if(k!=t.k)return k<t.k;return b>t.b;} }line[N];int st[N],tp;double get_x(int i,int j)//y=k1x+b1,y=k2x+b2,前式減后式,得到x=-1.0*(b1-b2)/(k1-k2),得到x的坐標 {return (-1.0*(line[i].b-line[j].b))/(1.0*(line[i].k-line[j].k)); }map<pair<LL,LL>,int>mp;int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;while(w--){mp.clear();int n;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%lld%lld",&line[i].b,&line[i].k);line[i].b*=2;//因為只需要求交點的相對位置,所以x和y軸同時放大兩倍,避免出現(xiàn)1/2mp[make_pair(line[i].b,line[i].k)]++;}sort(line+1,line+1+n);tp=0;for(int i=1;i<=n;i++){if(line[i].k==line[i-1].k)//兩直線平行 continue;while(tp&&line[i].b>=line[st[tp]].b)//如果當前直線在棧頂?shù)闹本€上面,說明棧頂?shù)闹本€不可能被看到 tp--;while(tp>1&&sgn(get_x(st[tp-1],st[tp])-get_x(st[tp],i))>=0)tp--;st[++tp]=i;}int ans=0;for(int i=1;i<=tp;i++){if(mp[make_pair(line[st[i]].b,line[st[i]].k)]==1)ans++;}printf("%d\n",ans);}return 0; }

?

總結(jié)

以上是生活随笔為你收集整理的HDU多校1 - 6759 Leading Robots(单调栈)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。