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;
}
posted @ 2012-05-01 11:15  Because Of You  Views(523)  Comments(0Edit  收藏  举报