【bzoj 2383】ballons(單調棧)

傳送門biu~
對於一個氣球i,如果它左邊的某個氣球j的右邊有比j大的氣球,顯然j不會對i的大小產生影響。所以能夠影響氣球i的大小的氣球集合是座標遞增半徑遞減的。
我們把這些氣球放在一個棧裏,從棧頂的氣球開始考慮其對第i個氣球的影響。第i個氣球的半徑初始化爲上限ri,然後用棧頂的氣球更新半徑。
如果更新後第i個氣球的半徑比棧頂氣球半徑大,那麼這個棧頂之後就沒有用了,彈棧。如果此時棧非空,那麼繼續考慮新的棧頂對第i個氣球的影響。
如果更新後第i個氣球的半徑比棧頂氣球半徑小,考慮在棧頂氣球的左側的氣球。既然棧頂的氣球在第i個氣球的左側且現在半徑比第i個氣球大,那麼棧頂氣球左側的氣球顯然就不能碰到第i個氣球。
此時棧裏的其它氣球不再對第i個氣球的大小產生影響。我們此時得到了第i個氣球的最終答案,把第i個氣球扔到棧裏就可以繼續考慮第i+1個氣球了。

#include<bits/stdc++.h>
#define N 200005
using namespace std;
int n,q[N],top;
double x[N],r[N];
inline double Cut(int i,int j){return (x[i]-x[j])*(x[i]-x[j])/(4*r[i]);}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%lf%lf",&x[i],&r[i]);
        while(top){
            r[i]=min(r[i],Cut(q[top],i));
            if(r[q[top]]<r[i]) --top;
            else break;
        }
        q[++top]=i;
        printf("%.3lf\n",r[i]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章