hdu - 4302 - Holedox Eating - 线段树

线段树。http://acm.hdu.edu.cn/showproblem.php?pid=4302

求距离离某点距离最短的点的下标。

刚开始初始化的时候没初始对, Orz了好久。还以为有什么问题呢。

#include <cstdio>
#include <iostream>
#define inf 100010
#define maxn 100010
#define ls rt << 1
#define rs rt << 1 | 1
#define lson l, m , rt << 1
#define rson m + 1, r, rt << 1 | 1
#define havem int m = (l + r) >> 1
using namespace std;
int T,n, Q, op, pos, now, dir, ans;
int val[maxn << 2], mmax[maxn << 2], mmin[maxn << 2];
void build(int l, int r, int rt){
    val[rt] = 0;
    mmax[rt] = -inf;
    mmin[rt] = inf;
    if(l == r) return ;
    havem;
    build(lson); build(rson);
}
void update(int pos, int cc, int l,int r, int rt){
    if(l == r) {
        val[rt] += cc;
        if(val[rt]){
            mmax[rt] = mmin[rt] = pos;//
        }else{
            mmax[rt] = -inf;
            mmin[rt] = inf;
        }
        return ;
    }havem;
    if(pos <= m) update(pos,cc,lson);
    else update(pos,cc,rson);
    mmax[rt] = max(mmax[ls], mmax[rs]);
    mmin[rt] = min(mmin[ls], mmin[rs]);
}
int find_max(int L, int R, int l, int r, int rt){
    if(L <= l && r <= R){
        return mmax[rt];
    }
    int ret = -inf; havem;
    if(L <= m) ret = find_max(L,R,lson);
    if(R > m) ret = max( ret,find_max(L,R,rson) );
    return ret;
}
int find_min(int L, int R, int l, int r, int rt){
    if(L <= l && r <= R){
        return mmin[rt];
    }
    int ret = inf; havem;
    if(L <= m) ret = find_min(L,R,lson);
    if(R > m) ret = min( ret,find_min(L,R,rson) );
    return ret;
}
int main(){
    scanf("%d",&T);
    for(int ca = 1; ca <= T; ca ++){
        scanf("%d%d",&n, & Q);
        build(0,n,1);
        now = 0, dir = 1, ans = 0;
        for(int i = 0; i < Q; ++ i){
            scanf("%d", & op);
            if(op == 0){
                scanf("%d",&pos);
                update(pos, 1, 0, n, 1);
            }else{
                int l = find_max(0, now, 0, n, 1);
                int r = find_min(now, n, 0, n, 1);

                if(l <= -inf && r >= inf){
                    continue;
                }else if(l <= -inf){
                    ans += r - now, now = r, dir = 1;
                }else if(r >= inf){
                    ans += now - l, now = l, dir = 0;
                }else if(now - l < r - now){
                    ans += now - l, now = l, dir = 0;
                }else if(now - l > r - now){
                    ans += r - now, now = r, dir = 1;
                }else {
                    if(dir){
                        ans += r - now, now = r;
                    }else{
                        ans += now - l, now = l;
                    }
                }//printf("%d %d %d  kaka\n", l, r, now);
                update(now, -1, 0, n, 1);
            }
        }
        printf("Case %d: %d\n", ca, ans);
    }
    return 0;
}

这题优先队列就可以过, Orz。。。

priority_queue<int> L;  //大顶堆  
priority_queue<int,vector<int>,greater<int> > R; //小顶堆  
  
  
int main()  
{  
    int T;  
    scanf("%d",&T);  
    for(int cas=1;cas<=T;cas++)  
    {  
        while(!L.empty()) L.pop();  
        while(!R.empty()) R.pop();  
        int len,n,pos=0,dir=1;  
        __int64 ans=0;  
        scanf("%d%d",&len,&n);  
        for(int i=0;i<n;i++)  
        {  
            int flag;  
            scanf("%d",&flag);  
            if(!flag)  
            {  
                int temp;  
                scanf("%d",&temp);  
                if(temp>pos)  
                    R.push(temp);  
                else  
                    L.push(temp);  
            }  
            else  
            {  
                int l=-1000000,r=1000000;  
                if(L.empty() && R.empty()) continue;  
                if(!L.empty()) l=L.top();  
                if(!R.empty()) r=R.top();  
                if(r-pos<pos-l) dir=1;  
                else if(pos-l<r-pos) dir=0;  
                if(dir)  
                {  
                    ans+=r-pos;  
                    pos=r;  
                    R.pop();  
                }  
                else  
                {  
                    ans+=pos-l;  
                    pos=l;  
                    L.pop();  
                }  
            }  
        }  
        printf("Case %d: %I64d\n",cas,ans);  
    }  
    return 0;  
}  




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值