QOJ8917 2026 / luogu P11113 [ROI 2024] 2026 (Day 1) 题解
很容易发现如果连续的一段全是 L 或 R 或者全是 U 或 D,那么实际上这一整段可以被压缩成最后一个字符。
当我们把操作序列按照这种方式压缩后,相邻两个操作都是不同方向上的。我们考虑这种形状 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;
}

浙公网安备 33010602011771号