终于肝完了 hdu 3950 Parking Log (递归线段树/ZKW线段树)*2

这题情况真是很多,而且我看这题写题解的人不多,所以来写一下这个题

首先讲一下这个题的思路:

  • 用一棵线段树来维护空闲区间的信息(起始点,长度)
  • 再用另一颗线段树来维护车队信息(起始点,长度)

这个思路是从这个大佬的称述和代码中得到的.

然后我又简化了情况之后最后只有3类情况需要考虑

  1. 整段区间没有车队
  2. 需要插入的是中间区间
  3. 需要插入的是最后区间

只有一种情况会被归到第一类情况:没有车队的情况(PrevFree>m&&mcnt1==2)
有两种情况会被归到第二类情况:第一个车队前的空位有足够空间(PrevFree>m)
                      或者查询到的空闲区间不是最后区间(pos!=INF&&pos+len!=n+1)
也有两种情况会被归到第三类情况:查询到的空闲区间是最后区间(pos!=INF&&pos+len==n+1)
                      或者最后车队后面的空位有足够空间(pos==INF&&len>=m)

话不多说,上代码(zkw线段树版):

#include<stdio.h>
#include<string.h>
#include<set>
#include<map>
const int INF=0x3F3F3F3F,INSERT=1,DELETE=0;
std::set<int>s[50005];std::map<int,int>flen;
int M,N,x,w,mcnt[1<<17],mlen[50005],fpos[1<<18];
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
void Fupdate(int pos,int len,int mode){
    if(len<=0)return;flen[pos]=len;
    if(mode)s[len].insert(pos);else s[len].erase(pos);
    fpos[len+N]=s[len].empty()?INF:*s[len].begin();
    for(len=len+N>>1;len;len/=2)
        fpos[len]=min(fpos[len*2],fpos[len*2+1]);
}
int Fquery(int l,int r){
    for(x=INF,l+=N-1,r+=N+1;l^r^1;l/=2,r/=2){
        if(~l&1)x=min(x,fpos[l^1]);
        if( r&1)x=min(x,fpos[r^1]);
    }return x;
}
void Mupdate(int pos,int len,int mode){
    mlen[pos]=len*mode;pos++;mcnt[pos+=M]=mode;
    for(pos/=2;pos;pos/=2)mcnt[pos]=mcnt[pos*2]+mcnt[pos*2+1];
}
int Mquery(int rank){
    for(x=1;x<M;)
    if(rank<=mcnt[x*2])x=x*2;
    else rank-=mcnt[x*2],x=x*2+1;
    return x-M-1;
}
/*nc*/inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
/*cini*/int ch,res;
int cini(){
    while((ch=nc())<'0'||ch>'9');res=ch-'0';
    while((ch=nc())>='0'&&ch<='9')res=res*10+ch-'0';
    return res;
}
int main(){
    int T=cini();
    for(int kase=1;kase<=T;kase++){
        printf("Case #%d:\n",kase);
        int n=cini(),q=cini();
        M=1;while(M<n+4)M*=2;
        N=1;while(N<n+2)N*=2;
        for(int i=0;i<50005;i++)
            if(!s[i].empty())s[i].clear();
        memset(fpos,0x3F,sizeof fpos);
        memset(mcnt,0x00,sizeof mcnt);
        memset(mlen,0x00,sizeof mlen);
        flen.clear();flen[INF]=INF;
        Fupdate(1-0,n,INSERT);
        Mupdate(1-1,1,INSERT);
        Mupdate(n+1,1,INSERT);
        while(q--){
            if(nc()=='A'){
                int PrevFree,LastFree,ans;
                int m=cini(),l=cini(),r=cini();
                if(m>n){puts("-1");continue;}
                PrevFree=Mquery(2);
                LastFree=Mquery(mcnt[1]-1);
                LastFree=n+1-LastFree-mlen[LastFree];
                int pos=Fquery(m,min(n,m+l+r)),len=flen[pos];
                if(PrevFree>m&&mcnt[1]==2){
                    Fupdate(1,PrevFree-1,DELETE);
                    Mupdate(ans=1,m,INSERT);
                    Fupdate(m+1,n-m,INSERT);
                }else if(PrevFree>m||(pos!=INF&&pos+len!=n+1)){
                    if(PrevFree>m)pos=1,len=PrevFree-1;
                    if(len>l+m+r)ans=-1;
                    else{
                        Fupdate(pos,len,DELETE);
                        Mupdate(ans=pos+max(0,len-r-m),m,INSERT);
                        Fupdate(pos,ans-pos,INSERT);
                        Fupdate(ans+m,pos+len-ans-m,INSERT);
                    }
                }else{
                    if(pos==INF)len=LastFree,pos=n+1-len;
                    if(len<m)ans=-1;
                    else{
                        Fupdate(pos,len,DELETE);
                        Mupdate(ans=pos,m,INSERT);
                    }
                }
                printf("%d\n",ans);
            }else{
                int k=cini()+1;
                if(k<=0||k>=mcnt[1])continue;
                int last=Mquery(k-1),curr=Mquery(k+0),next=Mquery(k+1);
                w=last+mlen[last];Fupdate(w,curr-w,DELETE);
                w=curr+mlen[curr];Fupdate(w,next-w,DELETE);
                w=last+mlen[last];Fupdate(w,next-w,INSERT);
                Mupdate(curr,mlen[curr],DELETE);
            }
        }
    }
    return 0;
}

递归版是我从dalao的代码中化简得到的,原来的代码在上面的传送门里:
有很多参数调整,变量名调整.为了更易读吧…

#include<bits/stdc++.h>
using namespace std;
const int MAXN=51000 + 1000;
const int INF = 0x3f3f3f3f;
const int INSERT=1;
const int DELETE=0;
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (L+R>>1)
#define lson L,mid,ls
#define rson mid+1,R,rs
struct TreeNode{
    int pos,len;
}FreeInterval[MAXN<<2],CadeRank[MAXN<<2];
set<int>s[MAXN];
int n;
void FreeInterval_build(int L=1,int R=n,int rt=1){
    if(L==R){
        s[L].clear();
        FreeInterval[rt].pos=INF;
        FreeInterval[rt].len=L;
        return ;
    }
    FreeInterval_build(lson);
    FreeInterval_build(rson);
    FreeInterval[rt]=FreeInterval[rt*2];
}
void FreeInterval_update(int pos,int len,int flag,int L=1,int R=n,int rt=1){
    if(L==R){
        if(flag){
            s[L].insert(pos);
            FreeInterval[rt].pos=*s[L].begin();
        }else{
            s[L].erase(pos);
            FreeInterval[rt].pos=INF;
            if(!s[L].empty())
                FreeInterval[rt].pos=*s[L].begin();
        }
        FreeInterval[rt].len=L;
        return ;
    }
    if(len<=mid)
        FreeInterval_update(pos,len,flag,lson);
    else
        FreeInterval_update(pos,len,flag,rson);
    FreeInterval[rt]=FreeInterval[rt*2+(FreeInterval[ls].pos>FreeInterval[rs].pos)];
}
TreeNode FreeInterval_query(int l,int r,int L=1,int R=n,int rt=1){
    if(l<=L&&R<=r)return FreeInterval[rt];
    TreeNode t1,t2;t1.pos=INF;t2.pos=INF;
    if(l<=mid)t1=FreeInterval_query(l,r,lson);
    if(r> mid)t2=FreeInterval_query(l,r,rson);
    return t1.pos<t2.pos?t1:t2;
}
void CadeRank_update(int pos,int len,int flag,int L=0,int R=n+1,int rt=1){
    if(L==R){
        CadeRank[rt].pos=flag;
        CadeRank[rt].len=len*flag;
        return ;
    }
    if(pos<=mid)CadeRank_update(pos,len,flag,lson);
    else CadeRank_update(pos,len,flag,rson);
    CadeRank[rt].pos=CadeRank[ls].pos+CadeRank[rs].pos;
}
void CadeRank_query(int rank,int &pos,int &len,int L=0,int R=n+1,int rt=1){
    if(L==R){
        pos=L;
        len=CadeRank[rt].len;
        return ;
    }
    if(rank<=CadeRank[ls].pos)
        CadeRank_query(rank,pos,len,lson);
    else
        CadeRank_query(rank-CadeRank[ls].pos,pos,len,rson);
}
int main(){
    int t,cas=0,q;
    scanf("%d",&t);
    while(t--){
        printf("Case #%d:\n",++cas);
        scanf("%d %d",&n,&q);
        FreeInterval_build();
        memset(CadeRank,0,sizeof CadeRank);
        FreeInterval_update(1,n,INSERT);
        CadeRank_update(0,1,INSERT);
        CadeRank_update(n+1,1,INSERT);
        int PrevFree=n,LastFree=n;
        char ch;
        int mi,li,ri,k;
        int where,len,ans;
        for(int i=0;i<q;i++){
            scanf(" %c",&ch);
            if(ch=='A'){//TRY TO INSERT A MOTORCADE LENGTH IS MI,CONSTRAINT IS LI&RI
                scanf("%d%d%d",&mi,&li,&ri);
                if(PrevFree>=mi){//ABLE TO INSERT INTO TOTAL'S BEGIN
                    FreeInterval_update(1,PrevFree,DELETE);
                    if(PrevFree==n){//NO MOTORCADE
                        if(n-mi>0)//HAVE FREE INTERVAL(AFTER)
                            FreeInterval_update(mi+1,n-mi,INSERT);//POS IS MI+1,LEN IS N-MI
                        CadeRank_update(1,mi,INSERT);//THERE IS A MOTORCADE POS IS 1,LEN IS MI
                        PrevFree=0;//PREFREEPOS IS 0
                        LastFree=n-mi;//FINALCADEPOS IS N-MI
                        ans=1;//ANS IS 1(TOTAL'S BEGIN)
                    }else{//EXIST MOTORCADE
                        //BECAUSE WILL INSERT INTO TOTAL'S BEGIN ,SO NOT CONSIDER LI
                        if(PrevFree>=mi+ri){//MUST HAVE FREE INTERVAL(BETWEEN),BUT NEED CALC 'WHERE' BECAUSE OF CONSTRAINT
                            where=PrevFree-ri+1;//FREE INTERVAL START POSITION
                            len=ri;//LENGTH IS RI
                            FreeInterval_update(where,len,INSERT);//UPDATE FREE INTERVAL
                            CadeRank_update(where-mi,mi,INSERT);//NEW MOTORCADE POSITION IS PREFREEPOS+1-RI-MI,LENGTH MUST IS MI
                            ans=where-mi;//ANS IS PREFREEPOS+1-RI-MI
                            PrevFree=PrevFree-mi-ri;//UPDATE PREFREEPOS
                            if(PrevFree)//IF PREFREEPOS IS 0,MEANING THERE IS NO FREE INTERVAL AT TOTAL'S BEGIN
                                FreeInterval_update(1,PrevFree,INSERT);//INSERT A FREE INTERVAL INTO TOTAL'S BEGIN
                        }else{//BECAUSE OF CONSTRAINT,POS MUST IS 0,SO NO FREE INTERVAL(BEFORE)
                            len=PrevFree-mi;//LENGTH OF GAP BETWEEN NEED_INSERT_MOTORCADE AND NEXT_MOTORCADE
                            if(len)//IF LEN!=0,THAT IS MEANING HAVE FREE INTERVAL
                                FreeInterval_update(mi+1,len,INSERT);
                            CadeRank_update(1,mi,INSERT);//THERE IS A MOTORCADE POS IS 1,LEN IS MI
                            ans=1;//ANS MUST IS 1(TOTAL'S BEGIN)
                            PrevFree=0;//PREFREEPOS IS 0
                        }
                    }
                }else{//CONSIDER OTHER POSITION EXCEPT TOTAL'S BEGIN
                    TreeNode tx=FreeInterval_query(mi,mi+li+ri);//QUERY WHETHER THERE HAVE LENGTH IN RANGE(MI,MI+LI+RI)
                    if(tx.pos==INF){//NO QUERYED FREE INTERVAL IN MIDDLE
                        if(LastFree>=mi){//IF CAN INSERT AFTER
                            FreeInterval_update(n-LastFree+1,LastFree,DELETE);//FIRST DELETE FINAL FREE INTERVAL
                            where=n-(LastFree-mi)+1;//NEW FREE INTERVAL START POSITION
                            len=LastFree-mi;//NEW FREE INTERVAL LENGTH
                            LastFree-=mi;//UPDATE FINALCADEPOS,DECREASE MI
                            if(len)//IF THERE HAVE ROOM TO BE INSERTED A FREE INTERVAL
                                FreeInterval_update(where,len,INSERT);
                            CadeRank_update(where-mi,mi,INSERT);//INSERT A NEW MOTORCADE
                            ans=where-mi;//ANS IS WHERE-MI
                        }
                        else
                            ans=-1;//CAN'T INSERT ANYWHERE
                    }else{//GET A QUERYED FREE INTERVAL IN MIDDLE
                        FreeInterval_update(tx.pos,tx.len,DELETE);//AT FIRST,DELETE GOT INTERVAL
                        if(tx.pos+tx.len-1==n){//GOT INTERVAL IS FINAL INTERVAL
                            ans=tx.pos;
                            LastFree=len=LastFree-mi;
                            if(len)
                                FreeInterval_update(tx.pos+mi,len,INSERT);
                            CadeRank_update(tx.pos,mi,INSERT);
                        }else if(tx.len>=mi+ri){//MUST KEEP DISTANCE BETWEEN LAST_CADE
                            len=tx.len-(mi+ri);//NEW FREE INTERVAL(BETWEEN LAST_CADE)
                            if(len)//IF EXIST
                                FreeInterval_update(tx.pos,len,INSERT);
                            FreeInterval_update(tx.pos+len+mi,ri,INSERT);//NEW FREE INTERVAL(BETWEEN NEXT_CADE)
                            CadeRank_update(tx.pos+len,mi,INSERT);//INSERT A NEW MOTORCADE
                            ans=tx.pos+len;//ANS
                        }else{//NO NEED KEEP DISTANCE BETWEEN LAST_CADE
                            len=tx.len-mi;//NEW FREE INTERVAL(BETWEEN NEXT_CADE)
                            if(len)//IF EXIST
                                FreeInterval_update(tx.pos+mi,len,INSERT);
                            CadeRank_update(tx.pos,mi,INSERT);//INSERT A NEW MOTORCADE
                            ans=tx.pos;//ANS
                        }
                    }
                }
                printf("%d\n",ans);//PRINT ANS
            }else{//TRY TO DELETE K-TH MOTORCADE
                scanf("%d",&k);++k;
                int where1,len1,where2,len2,where3,len3;
                if(k<CadeRank[1].pos){
                    CadeRank_query(k-1,where1,len1);//QUERY LAST MOTORCADE
                    CadeRank_query(k,where2,len2);//QUERY NEED MOTORCADE
                    CadeRank_query(k+1,where3,len3);//QUERY NEXT MOTORCADE
                    CadeRank_update(where2,len2,DELETE);//DELETE NEED MOTORCADE
                    len=where2-(where1+len1);//IF THERE IS GAP BETWEEN LAST AND NEED
                    if(len>0)
                        FreeInterval_update(where1+len1,len,DELETE);
                    len=where3-(where2+len2);//GAP BETWEEN NEED AND NEXT
                    if(len>0)
                        FreeInterval_update(where2+len2,len,DELETE);
                    len=where3-(where1+len1);//EMMMM...THIS LEN SHOULD MUST BIGGER THAN 0
                    if(len>0)
                        FreeInterval_update(where1+len1,len,INSERT);//INSERT A NEW INTERVAL
                    if(where1==0)//IF NOW MOTORCADE IS FIRST LEGAL MOTORCADE(AND BE DELETED)
                        PrevFree=len;//NEED TO UPDATE PREFREEPOS
                    if(where3==n+1)//IF NOW MOTORCADE IS LAST LEGAL MOTORCADE(AND BE DELETED)
                        LastFree=len;//NEED TO UPDATE FINALCADEPOS
                }
            }
        }
    }
    return 0;
}

真的崩溃了,为什么同样的代码C++能过G++不能过,有的是G++能过C++不能,超诡异的…
用nc优化的话能快但是只能上C++,不用的话只能上G++

nc函数优化的是C++

猜你喜欢

转载自blog.csdn.net/qq_30396205/article/details/82056192