CF 135 E.Parking Lot(线段树)

转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526       by---cxlove

题目:给出1-n个停车场,陆续有车子进来 ,每次选择一个位置,要求这个位置距离两边最近的车子的距离要最远,如果有相同的位置,取标号最小的。

和POJ 的hotel类似,记录区间的最大间隔,以及左端点的最大间隔,右端点的最大间隔。以及最大间隔的起始点

其中更新部分较为复杂,这里Debug了我两个小时,泪奔。。。

由于 题目要求取标号最小的,所以这里的判断顺序不可以乱,严格从左到右的顺序。

对于区间的最大间隔,可能是从左端点开始,这样的起始是最小的,所以要最早判断

接下来可能是左区间的最大间隔

然后是左区间的右间隔与右区间的左间隔的并

然后是右区间的最大间隔

最后是右端点。

开始凭感觉,随便YY了,然后Debug了两个小时,如果出现间隔相同的,按以上顺序才能保证标号最小。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define eps 1e-10
#define N 200005
#define inf 1<<20
#define zero(a) (fabs(a)<eps)
#define lson (step<<1)
#define rson (step<<1|1)
using namespace std;
struct Node{
    int left,right,mid;
    int mx,lx,rx,val;
    int dist(){return right-left+1;}
}L[N*4];
int pos[1000005];
void Bulid(int step,int l,int r){
    L[step].left=l;
    L[step].right=r;
    L[step].mid=(l+r)/2;
    L[step].mx=L[step].rx=L[step].lx=L[step].dist();
    L[step].val=l;
    if(l==r)
       return ;
    Bulid(lson,l,L[step].mid);
    Bulid(rson,L[step].mid+1,r);
}
void Push_Up(int step){
    L[step].lx=L[lson].lx+(L[lson].lx==L[lson].dist()?L[rson].lx:0);
    L[step].rx=L[rson].rx+(L[rson].rx==L[rson].dist()?L[lson].rx:0);
    //初始化为最左区间
    L[step].mx=L[step].lx;L[step].val=L[step].left;
    //左区间的最大间隔
    if(L[lson].mx>L[step].mx+1||(L[lson].mx>L[step].mx&&L[step].mx%2==0)){
        L[step].mx=L[lson].mx;
        L[step].val=L[lson].val;
    }
    //左区间的右端与右区间左端的并
    if(L[lson].rx+L[rson].lx>L[step].mx+1||(L[lson].rx+L[rson].lx>L[step].mx&&L[step].mx%2==0)){
        L[step].mx=L[lson].rx+L[rson].lx;
        L[step].val=L[lson].right-L[lson].rx+1;
    }
    //右区间的最大间隔
    if(L[rson].mx>L[step].mx+1||(L[rson].mx>L[step].mx&&L[step].mx%2==0)){
        L[step].mx=L[rson].mx;
        L[step].val=L[rson].val;
    }
    //右端点
    if(L[step].rx>L[step].mx+1||(L[step].rx>L[step].mx&&L[step].mx%2==0)){
        L[step].mx=L[step].rx;
        L[step].val=L[step].right-L[step].rx+1;
    }
}
void update(int step,int p,int k){
    if(L[step].left==L[step].right){
        //K为1表示停入一辆车
        if(k){
            L[step].mx=L[step].rx=L[step].lx=0;
            L[step].val=N;
        }
        else{
            L[step].mx=L[step].rx=L[step].lx=1;
            L[step].val=L[step].left;
        }
        return ;
    }
    if(p<=L[step].mid) update(lson,p,k);
    else update(rson,p,k);
    Push_Up(step);
}
int main(){
    int n,q;
  //  freopen("1.in","r",stdin);
 //  freopen("1.out","w",stdout);
    while(scanf("%d%d",&n,&q)!=EOF){
        Bulid(1,1,n);
        int cnt=1;
        while(q--){
            int ope,id;
            scanf("%d%d",&ope,&id);
            if(ope==2)   update(1,pos[id],0);
            else{
                int len=L[1].mx,val=L[1].val,ret;
                //如果最长的区间是连着右端点,需要特殊考虑
                if(val+len-1==n){
                    if(val==1) ret=1;
                    else ret=n;
                }
                else{
                    ret=1;                //特殊考虑左端点
                    int mmax=L[1].lx-1;   //如果放在左端点时的间隔
                    //考虑最长的区间
                    if((len-1)/2>mmax){
                        mmax=(len-1)/2;
                        ret=val+(len-1)/2;
                    }
                    //考虑右端点
                    if(L[1].rx-1>mmax){
                        mmax=L[1].rx-1;
                        ret=n;
                    }
                }
                printf("%d\n",ret);
                pos[id]=ret;
                update(1,ret,1);
            }
        }
    }
    return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值