洛谷P3434 [POI2006]KRA-The Disks(线段树)

洛谷题目传送门
\(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;
}

转载于:https://www.cnblogs.com/flashhu/p/8465968.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值