cf1494C

传送门

首先题目中的箱子只能往一个方向推,因此正负的解决方法是一样的。

当我们一个个向前推箱子的时候,我们不妨把一个个相接的箱子想象成火车的车厢,把特殊的位置想做站台,然后在刚开始会有一些车厢位于站台,然后题目就可以转化为最多有多少车厢可以同时听到站台。
别问我为什么站台只能放一个车厢

这样我们可以首先求出恰好在站台的车箱数,然后从前往后枚举车站,即火车头恰好到达这个车站,并求出当前火车的长度,及当前车厢可以覆盖的站台数,这个站台数分为两部分,一个是正在向右移的列车所占据的站台数,一个是还未合并但未在站台的车厢数,均可以线性求出。至此复杂度为\(O(n+m)\)

int T;
vector<int>al,ar,bl,br;
map<int,int>s,ss;
int solve(vector<int> &a,vector<int> &b){
    if(a.size()==1||b.size()==1) return 0;
    int n=a.size()-1,m=b.size()-1;
    s.clear();ss.clear();
    int sum=0,ans=0;
    rep(i,1,n) ss[a[i]]=1;
    rep(i,1,m) {
        if(ss[b[i]])s[b[i]]=1,sum++;
    }
    
    int l=1,pos=0;
    ans=sum;
    rep(i,1,m){
        if(s[b[i]]) sum--;
        while(a[pos+1]<=b[i]&&pos<n) pos++;
        while(b[i]-pos+1>b[l]) l++;
        ans=max(ans,i-l+1+sum);    
    }
    return ans;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in0.txt","r",stdin);
   // freopen("2.out","w",stdout);
#endif
    T=read();
    while(T--){
        int tmp;int n,m;
        al.clear(),ar.clear();
        bl.clear();br.clear();
        al.pb(0);ar.pb(0);
        bl.pb(0);br.pb(0);
        n=read(),m=read();
        rep(i,1,n){
            tmp=read();
            if(tmp<0) al.pb(-tmp);
            else ar.pb(tmp); 
        }
        rep(j,1,m) {
            tmp=read();
            if(tmp<0) bl.pb(-tmp);
            else br.pb(tmp);
        }
        int a;
        reverse(al.begin()+1,al.end());
        reverse(bl.begin()+1,bl.end());
        print(solve(al,bl)+solve(ar,br));pts;
    }
    return 0;
}
posted @ 2021-03-08 20:23  Mr_cold  阅读(48)  评论(0编辑  收藏  举报