洛谷P3434 [POI2006]KRA-The Disks(線段樹)
阿新 • • 發佈:2018-02-24
def spa uil ref post 直觀 char getchar ++i
洛谷題目傳送門
\(O(n)\)的正解算法對我這個小蒟蒻真的還有點思維難度。洛谷題解裏都講得很好。
考試的時候一看到300000就直接去想各種帶log的做法了,反正不怕T。。。。。。
我永遠只會有最直觀的思路(最差的程序效率)
題目相當於每次讓我們找區間\([1,las-1]\)中上數第一個比當前盤子半徑小的位置(las為上一次盤子掉到的位置)於是用線段樹無腦搞一下,維護區間最小值,每次找這個位置,能往左跳就往左,不能的話再往右,當然如果超過了las-1就不用找了,直接放在las上面(相當於las--)直到全部放完或las=0為止。
#include<cstdio> #define R register int #define lc u<<1 #define rc u<<1|1 #define G c=getchar() #define min2(x,y) x<y?x:y #define in(z) G; while(c<‘-‘)G; z=c&15;G; while(c>‘-‘)z*=10,z+=c&15,G const int N=300009,M=10000009; int las,k,a[N],mina[M];//mina記錄最小值 void build(R u,R l,R r){ if(l==r){ mina[u]=a[l]; return; } R m=(l+r)>>1; build(lc,l,m);build(rc,m+1,r); mina[u]=min2(mina[lc],mina[rc]); } int ask(R u,R l,R r){ if(l==r)return l-1; R m=(l+r)>>1; //因為要找位置最靠前的,所以優先往左 if(mina[lc]<k)return ask(lc,l,m); if(m<las-1&&mina[rc]<k)return ask(rc,m+1,r);//m要小於las-1 return las-1; } int main(){ R n,m; register char c; in(n);in(m);las=n+1; for(R i=1;i<=n;++i){in(a[i]);} build(1,1,n); while(m--&&las){//las=0直接就不放了 in(k); las=ask(1,1,n); } printf("%d\n",las); return 0; }
洛谷P3434 [POI2006]KRA-The Disks(線段樹)