codeforces 46D 线段树 区间合并

和poj 的hotel差不多,多了一些细节处理的过程

给一辆汽车安排空位的时候还需要和前后的车都保持一定的车距,如果前面没车或者后面没车,则可以停在边界上

典型的线段树区间合并

View Code
#include<cstdio>

#include<cstring>

#include<vector>

#include<map>

#include<algorithm>

using namespace std;

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

const int maxn = 200010;

int sum[maxn<<2],col[maxn<<2];

int lsum[maxn<<2],rsum[maxn<<2];

map<int,pair<int,int> >re;

inline int max(int a,int b){

    return a>b?a:b;

}

void pushup(int rt,int m){

    lsum[rt]=lsum[rt<<1];

    rsum[rt]=rsum[rt<<1|1];

    if(lsum[rt]==(m-(m>>1))) lsum[rt]+=lsum[rt<<1|1];

    if(rsum[rt]==(m>>1)) rsum[rt]+=rsum[rt<<1];

    sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);

    sum[rt]=max(rsum[rt<<1]+lsum[rt<<1|1],sum[rt]);

}

void pushdown(int rt,int m){

    if(col[rt]!=-1){

        lsum[rt<<1]=rsum[rt<<1]=sum[rt<<1]=col[rt] ? m-(m>>1) : 0 ;

        lsum[rt<<1|1]=rsum[rt<<1|1]=sum[rt<<1|1]=col[rt] ? (m>>1): 0;

        col[rt]=-1;

    }

}

void build(int l,int r,int rt){

    lsum[rt]=rsum[rt]=sum[rt]=r-l+1;

    col[rt]=-1;

    if(l==r)  return ;

    int m=(l+r)>>1;

    build(lson);

    build(rson);

}

void update(int L,int R,int c,int l,int r,int rt){

    if(L<=l&&r<=R){

        lsum[rt]=rsum[rt]=sum[rt]= c ? r-l+1:0;

        col[rt]=c;

        return ;

    }

    pushdown(rt,r-l+1);

    int m=(l+r)>>1;

    if(L<=m) update(L,R,c,lson);

    if(R>m) update(L,R,c,rson);

    pushup(rt,r-l+1);

}

int query(int w,int l,int r,int rt){

    if(l==r) return l;

    pushdown(rt,r-l+1);

    int m=(l+r)>>1;

    if(sum[rt<<1]>=w) return query(w,lson);

    else if(rsum[rt<<1]+lsum[rt<<1|1]>=w) return m-rsum[rt<<1]+1;

    else return query(w,rson);

}

int main()

{

    int n,m,behind,front,op,a,b,pos,ops;

    while(scanf("%d%d%d",&n,&behind,&front)!=EOF)

    {

        ops=0;

        build(0,n-1+front,1);

        scanf("%d",&m);

        while(m--)

        {

            scanf("%d%d",&op,&a);

            ops++;

            if(op==1)

            {

                if(sum[1]>=a+behind+front || lsum[1] >= a+front)

                {

                    if(lsum[1]>=a+front) pos=0;

                    else  pos=query(a+behind+front,0,n-1+front,1);

                    if(pos!=0) 

                    {

                        printf("%d\n",pos+behind);

                        update(pos+behind,pos+behind+a-1,0,0,n-1+front,1);

                        re[ops]=make_pair(pos+behind,pos+behind+a-1);

                    }

                    else

                    {

                        printf("0\n");

                        update(0,a-1,0,0,n-1+front,1);

                        re[ops]=make_pair(0,a-1);

                    }

                }

                else printf("-1\n");

            }

            else

            {

                int l=(int)re[a].first,r=(int)re[a].second;

                update(l,r,1,0,n-1+front,1);

            }

        }

    }

    return 0;

}

 

 

哥用线段树调了n久,神牛们却用如此简短的代码让我 汗颜

分析:因为需要插入的次数很小,所以可以直接记录,每辆汽车一次插入的位置,被占据的位置和空位间肯定是一段一段相邻的

即,比如有空位 a-b、c-d,       b-c  被占据了,如果a-b不够长,那么指针就要往右移动两个位置了,即跳过中间被占据的位置

View Code
#include <cstdio>

#include <cstring>

#include <vector>

#include <set>

#include <algorithm>

using namespace std;

int L, B, F;

int pos[105][2], tm=0;

set<int> s;

int main(void) {

    scanf("%d%d%d", &L, &B, &F);

    s.insert(-B);

    s.insert(L+F);

    int n;

    scanf("%d", &n);

    while(n--) {

        int x, y;

        scanf("%d%d", &x, &y);

        ++tm;

        if (x == 1) {

            int f=0;

            for(set<int>::iterator it=s.begin(); it!=s.end(); ) {

                set<int>::iterator nxt=it;

                ++nxt;

                if (nxt!=s.end() && ((*it)+B+y+F <= *nxt)) {

                    printf("%d\n", (*it)+B);

                    s.insert((*it)+B);

                    s.insert((*it)+B+y);

                    pos[tm][0] = *it+B;

                    pos[tm][1] = *it+B+y;

                    f=1;

                    break;

                }

                ++it; if(it!=s.end()) ++it;

            }

            if(!f) puts("-1");

        } else {

            s.erase(pos[y][0]);

            s.erase(pos[y][1]);

        }

    }

    return 0;

}

你可能感兴趣的:(codeforces)