QOJ8917 2026 / luogu P11113 [ROI 2024] 2026 (Day 1) 题解

link1 link2

很容易发现如果连续的一段全是 LR 或者全是 UD,那么实际上这一整段可以被压缩成最后一个字符。

当我们把操作序列按照这种方式压缩后,相邻两个操作都是不同方向上的。我们考虑这种形状 LUL,会发现其实第二个 L 是无用的,可以被扔掉。这种隔一个相同的形状我们也可以压缩。

经过第二次压缩过后,你会发现序列只会变成这样:

LURDLURDLU...
RULDRULDRU...
LDRULDRULD...
RDLURDLURD...
...

也就是以前 \(4\) 个字符作为循环节的样子。

第一次循环除外,每经过一次循环,棋盘上棋子排列成的形状是不会变的,但是棋子可能会变。

我们可以把一次循环看作一次置换。对于每个位置,我们记录 \(to_{i,j}\) 为经过一次置换后 \((i,j)\) 会到达哪个位置。可以发现置换一定是由若干个环组成的,我们将这些环全部找到,就可以快速处理了。

#include<bits/stdc++.h>
using namespace std;
int T,n,m,q;string s;
void upd(vector<vector<pair<int,int> > > &a,char op){
    if(op=='L'){
        for(int i=1;i<=n;i++){
            vector<pair<int,int> > v;
            for(int j=1;j<=m;j++)
                if(a[i][j].first)
                    v.push_back(a[i][j]);
            for(int j=0;j<v.size();j++)a[i][j+1]=v[j];
            for(int j=v.size()+1;j<=m;j++)a[i][j]={0,0};
        }
    }else if(op=='R'){
        for(int i=1;i<=n;i++){
            vector<pair<int,int> > v;
            for(int j=1;j<=m;j++)
                if(a[i][j].first)
                    v.push_back(a[i][j]);
            for(int j=1;j<=m-v.size();j++)a[i][j]={0,0};
            for(int j=0;j<v.size();j++)a[i][j+m-v.size()+1]=v[j];
        }
    }else if(op=='U'){
        for(int i=1;i<=m;i++){
            vector<pair<int,int> > v;
            for(int j=1;j<=n;j++)
                if(a[j][i].first)
                    v.push_back(a[j][i]);
            for(int j=0;j<v.size();j++)a[j+1][i]=v[j];
            for(int j=v.size()+1;j<=n;j++)a[j][i]={0,0};
        }
    }else{
        for(int i=1;i<=m;i++){
            vector<pair<int,int> > v;
            for(int j=1;j<=n;j++)
                if(a[j][i].first)
                    v.push_back(a[j][i]);
            for(int j=1;j<=n-v.size();j++)a[j][i]={0,0};
            for(int j=0;j<v.size();j++)a[j+n-v.size()+1][i]=v[j];
        }
    }
}
void Upd(vector<vector<char> > &a,char op){
    if(op=='L'){
        for(int i=1;i<=n;i++){
            vector<char> v;
            for(int j=1;j<=m;j++)
                if(a[i][j]!='.')
                    v.push_back(a[i][j]);
            for(int j=0;j<v.size();j++)a[i][j+1]=v[j];
            for(int j=v.size()+1;j<=m;j++)a[i][j]='.';
        }
    }else if(op=='R'){
        for(int i=1;i<=n;i++){
            vector<char> v;
            for(int j=1;j<=m;j++)
                if(a[i][j]!='.')
                    v.push_back(a[i][j]);
            for(int j=1;j<=m-v.size();j++)a[i][j]='.';
            for(int j=0;j<v.size();j++)a[i][j+m-v.size()+1]=v[j];
        }
    }else if(op=='U'){
        for(int i=1;i<=m;i++){
            vector<char> v;
            for(int j=1;j<=n;j++)
                if(a[j][i]!='.')
                    v.push_back(a[j][i]);
            for(int j=0;j<v.size();j++)a[j+1][i]=v[j];
            for(int j=v.size()+1;j<=n;j++)a[j][i]='.';
        }
    }else{
        for(int i=1;i<=m;i++){
            vector<char> v;
            for(int j=1;j<=n;j++)
                if(a[j][i]!='.')
                    v.push_back(a[j][i]);
            for(int j=1;j<=n-v.size();j++)a[j][i]='.';
            for(int j=0;j<v.size();j++)a[j+n-v.size()+1][i]=v[j];
        }
    }
}
void print(vector<vector<char> > a){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
            cout<<a[i][j];
        cout<<"\n";
    }
}
void Print(vector<vector<char> > a,vector<vector<pair<int,int> > > A){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
            cout<<a[A[i][j].first][A[i][j].second];
        cout<<"\n";
    }
}
void solve(){
    cin>>n>>m;
    vector<vector<char> > a(n+5,vector<char>(m+5,0));
    a[0][0]='.';
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>a[i][j];
    cin>>s;
    string t;
    for(char i:s){//对操作序列进行压缩
        if(i=='L'){
            while(!t.empty()&&(t.back()=='L'||t.back()=='R'))t.pop_back();
            if(!(t.size()>1&&t[t.size()-2]==i))t.push_back(i);
        }else if(i=='R'){
            while(!t.empty()&&(t.back()=='L'||t.back()=='R'))t.pop_back();
            if(!(t.size()>1&&t[t.size()-2]==i))t.push_back(i);
        }else if(i=='U'){
            while(!t.empty()&&(t.back()=='U'||t.back()=='D'))t.pop_back();
            if(!(t.size()>1&&t[t.size()-2]==i))t.push_back(i);
        }else{
            while(!t.empty()&&(t.back()=='U'||t.back()=='D'))t.pop_back();
            if(!(t.size()>1&&t[t.size()-2]==i))t.push_back(i);
        }
    }
    q=t.size();
    for(int i=0;i<min(4,q);i++)Upd(a,t[i]);
    if(q<=4){
        print(a);
        return;
    }
    vector<vector<pair<int,int> > > A(n+5,vector<pair<int,int> >(m+5,{0,0}));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(a[i][j]!='.')
                A[i][j]={i,j};
    vector<vector<pair<int,int> > > b=A;
    for(int i=4;i<min(8,q);i++)upd(A,t[i]);
    if(q<=8){
        Print(a,A);
        return;
    }
    vector<vector<pair<int,int> > > to(n+5,vector<pair<int,int> >(m+5,{0,0}));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(A[i][j].first)
                to[A[i][j].first][A[i][j].second]={i,j};
    vector<vector<bool> > vis(n+5,vector<bool>(m+5,0));
    vector<vector<pair<int,int> > > ans(n+5,vector<pair<int,int> >(m+5,{0,0}));
    int cnt=(q-4)/4;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(!b[i][j].first||vis[i][j])continue;
            pair<int,int> cur={i,j};
            vector<pair<int,int> > cyc;
            while(!vis[cur.first][cur.second]){
                vis[cur.first][cur.second]=1;
                cyc.push_back({cur.first,cur.second});
                cur=to[cur.first][cur.second];
            }
            for(int i=0;i<cyc.size();i++){
                pair<int,int> nxt=cyc[(i+cnt)%cyc.size()];
                ans[nxt.first][nxt.second]=b[cyc[i].first][cyc[i].second];
            }
        }
    }
    for(int i=cnt*4+4;i<q;i++)upd(ans,t[i]);
    Print(a,ans);
}
int main(){
    // freopen("twenty26.in","r",stdin);
    // freopen("twenty26.out","w",stdout);
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>T;
    while(T--)solve();
    return 0;
}
posted @ 2026-08-28 16:44  cqbzcjh  阅读(3)  评论(0)    收藏  举报