hdu 3950 Parking Log(单点更新)

题意: 有T组测试数据,每组数据的N和Q分别表示停车场有N个位置(下标从1开始),Q个操作。操作有两种(1)"A M L R",表示这个车队有M辆车,如果前面的空位,要求与前面的车的距离不超过L,如果后面有车,要求与后面的车的距离不超过R,如果前面或后面没有车,条件L,R的限制忽略,如果有满足条件的位置输出起点的下标,如果有多个满足条件的位置输出下标最小的一个,如果没有满足条件的位置,输出-1。(2)"B K",表示从左到右数第k个车队离开。

        要维护两个数据结构,一个是线段树,在叶子结点lft==rht==len保存长度为len的空闲区间的起点,因为优先取较小的起点,还要支持删除操作,所以用了set<int>去保存这些信息。在线段树的其他节点中保存这段区间中起点最小的空闲区间的起点和长度。另一个用树状数组来维护第k个车队的起点,从而快速得到第k个车队的起点是多少。

        对于所有可得的区间,我分成了三部分,用了两个变量去保存与1位置(停车场的起点)连接的空闲位置的长度st_len,和与N位置(停车场的终点)连接的空闲位置的长度ed_len,这个我们线段树只用来保存不与起点1和终点N相连的空闲区间的信息。

        对于A操作,当每次进行A操作时,我们每判断st_len是否满足条件,如果没有找到,在线段树中查找,如果再没有找到,判断ed_len是否满足条件,最后没有找到输出-1。如果找到了,那么还要将与前面的、后面车队的空隙加进可得的区间里。

        对于B操作,除了找出第k个车队的起点之外,还要找出k-1和k+1(如果没有需要特判)个车队的起点,与前后两个车队的空隙要从可得的区间里删除。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
using namespace std;
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a,b) (a+((b-a)>>1))
#define INF (1<<30)
const int N=50005;
int n,q,ed[N];
int st_len,ed_len;
struct Segtree
{
    set<int> T[N];
    int st[N*4],len[N*4];
    void PushUp(int ind)
    {
        if(st[LL(ind)]<st[RR(ind)])
        {
            st[ind]=st[LL(ind)];
            len[ind]=len[LL(ind)];
        }
        else
        {
            st[ind]=st[RR(ind)];
            len[ind]=len[RR(ind)];
        }
    }
    void build(int lft,int rht,int ind)
    {
        st[ind]=INF;
        if(lft==rht) T[lft].clear();
        else
        {
            int mid=MID(lft,rht);
            build(lft,mid,LL(ind));
            build(mid+1,rht,RR(ind));
        }
    }
    void updata(int pos,int ist,bool add,int ind,int lft,int rht)
    {
        if(lft==rht)
        {
            if(add) T[lft].insert(ist);
            else T[lft].erase(ist);
            if(T[lft].size()==0) st[ind]=INF;
            else
            {
                len[ind]=lft;    st[ind]=*(T[lft].begin());
            }
        }
        else
        {
            int mid=MID(lft,rht);
            if(pos<=mid) updata(pos,ist,add,LL(ind),lft,mid);
            else updata(pos,ist,add,RR(ind),mid+1,rht);
            PushUp(ind);
        }
    }
    pair<int,int> query(int ist,int ied,int ind,int lft,int rht)
    {
        if(ist<=lft&&rht<=ied) return make_pair(st[ind],len[ind]);
        else
        {
            int mid=MID(lft,rht);
            pair<int,int> tmp1,tmp2; tmp1.first=INF,tmp2.first=INF;
            if(ist<=mid) tmp1=query(ist,ied,LL(ind),lft,mid);
            if(ied> mid) tmp2=query(ist,ied,RR(ind),mid+1,rht);
            if(tmp1.first<tmp2.first) return tmp1;
            else return tmp2;
        }
    }
}seg;
struct BIT
{
    int T[N],sum;
    void init(){memset(T,0,sizeof(T));sum=0;}
    int lowbit(int x){return x&-x;}
    void insert(int x,int add)
    {
        sum+=add;
        while(x<N)
        {
            T[x]+=add; x+=lowbit(x);
        }
    }
    int query(int k)
    {
        int ind=0;
        for(int i=20;i>=0;i--)
        {
            ind^=(1<<i);
            if(ind<N&&k>T[ind]) k-=T[ind];
            else ind^=(1<<i);
        }
        return ind+1;
    }
    int getsum()
    {
        return sum;
    }
}bit;
int calu(int st,int len,int m,int a,int b)    
{
    int ed=st+len-1;
    return max(ed-m-b+1,st);
}
bool judge(int st1,int st2,int &ilen,int &ist) 
{
    ist=st1;
    if(st1>st2) return false;
    ilen=st2-st1+1;
    return true;
}
int main()
{
    int t,t_cnt=0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&q);

        seg.build(1,n,1);   bit.init();
        st_len=n,ed_len=n;

        printf("Case #%d:\n",++t_cnt);
        while(q--)
        {
            char cmd[5];     scanf("%s",cmd);
            if(cmd[0]=='A')
            {
                int m,a,b;     scanf("%d%d%d",&m,&a,&b);
                if(st_len>=m)     
                {
                    if(st_len==n)  
                    {
                        ed[1]=m; bit.insert(1,1); st_len=0; ed_len-=m;
                        printf("%d\n",1);
                    }
                    else            
                    {
                        int tmp=calu(1,st_len,m,a,b);     
                        ed[tmp]=tmp+m-1; bit.insert(tmp,1); 
                        printf("%d\n",tmp);

                        int len,st;
                        if(judge(ed[tmp]+1,st_len,len,st)) seg.updata(len,st,1,1,1,n);    
                        st_len=tmp-1;                     
                    }
                }
                else
                {
                    pair<int,int> res=seg.query(m,m+a+b,1,1,n);
                    if(res.first!=INF)
                    {
                        seg.updata(res.second,res.first,0,1,1,n); 
                        int tmp=calu(res.first,res.second,m,a,b);  
                        ed[tmp]=tmp+m-1;  bit.insert(tmp,1);        
                        printf("%d\n",tmp);

                        int len,st;
                        if(judge(res.first,tmp-1,len,st)) 	seg.updata(len,st,1,1,1,n);        
                        if(judge(ed[tmp]+1,res.first+res.second-1,len,st)) 	seg.updata(len,st,1,1,1,n);
                    }
                    else
                    {
                        if(ed_len<m) puts("-1");
                        else
                        {
                            int tmp=n-ed_len+1;
                            ed[tmp]=tmp+m-1; ed_len=n-ed[tmp];    bit.insert(tmp,1);
                            printf("%d\n",tmp);
                        }
                    }
                }
            }
            else
            {
                int k; scanf("%d",&k);

                if(k>bit.getsum()||k<=0) continue;  
                int st=bit.query(k);                 

                int st1=1;
                if(k>1) st1=ed[bit.query(k-1)]+1;    
                int len1=st-st1;                    
                if(len1>0&&st1!=1) seg.updata(len1,st1,0,1,1,n);    

                int st2=bit.query(k+1)-1,len2;        
                if(st2>n) len2=0,st2=n;
                else len2=st2-ed[st];

                if(len2>0&&!(st2==n)) seg.updata(len2,ed[st]+1,0,1,1,n);

                if(st1!=1&&st2!=n) seg.updata(st2-st1+1,st1,1,1,1,n);

                if(st1==1) st_len=st2-st1+1;
                if(st2==n) ed_len=st2-st1+1;            

                bit.insert(st,-1);
            }
        }
    }
    return 0;
}


你可能感兴趣的:(hdu 3950 Parking Log(单点更新))