题解:P11113 [ROI 2024 Day 1] 2026

· · 题解

第一回交题解,写的不好请见谅qaq

我们很容易可以发现以下三点

1 . 对于 LL 这种连续两个相同,可以只保留一个,即 LL

2 . 对于 LR 这种,可以只保留后面那个,即 LR;

3 . 对于 LUL 这种前后两个相同的,可以只保留前面那个,即 LRL

(第三个如果没看出来建议自己手动模拟一下)

那么如果有一个已经确定的 LU,后面为了不被消掉就只能接 R,递推下去得到 LURDLURD...容易看出来是在顺时针循环操作。同理可得也可以 LDRULDRU 地逆时针操作。那么在经过以上方式消除后,剩下的操作就变成了许多次的周期为4的循环。

这里消除操作我采用的是双向链表,在经过化简后的暴力可以拿到 43pts 的好成绩。

在知道剩下的操作序列是循环后,容易想到倍增优化,即算出一个循环会造成的影响,使用链表存储,然后倍增即可。

举例

abcdef...
ghijk....
lm.......
.........

这么一个矩阵在经过一次逆时针操作后会变成

lghcab...
mijde....
kf.......
.........

发现阶梯形状是一样的,只是位置变了,链表存储操作一周期后会走到哪个位置即可。

Talk is cheap,show me the code

码风魔鬼,谨慎入内

#include<bits/stdc++.h>
using namespace std;
// #define int long long
#define sfor(i,j,k) for(register int i=j;i<=k;++i)
#define dfor(i,j,k) for(register int i=k;i>=j;--i)
inline int read(){
    register int x = 0, t = 1;
    register char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            t=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*t;
}
inline void write(int x)
{
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
}
string s[2000006];
int ans[2000006],cyj[2000006],tto[2000006],pre[2000006],aft[2000006],n,m,f[2][2000006],la=0,sg=1,z[2000006],ca[2000006],fi[2000006];
inline int getnum(int x,int y) {return x*m+y-m;}
inline void U()
  {sfor(i,1,n*m) f[sg][i]=0;
   sfor(j,1,m)
    {int tt=0;
     sfor(i,1,n) if(f[la][getnum(i,j)]) z[++tt]=f[la][(getnum(i,j))];
     sfor(i,1,tt) f[sg][getnum(i,j)]=z[i];}
   swap(la,sg);return;
  }
inline void D()
  {sfor(i,1,n*m) f[sg][i]=0;
   sfor(j,1,m)
     {int tt=0;
      dfor(i,1,n) if(f[la][getnum(i,j)]) z[++tt]=f[la][(getnum(i,j))];
      sfor(i,1,tt) f[sg][getnum(n+1-i,j)]=z[i];}
   swap(la,sg);return;
  }
inline void L()
  {sfor(i,1,n*m) f[sg][i]=0;
   sfor(i,1,n)
     {int tt=0;
      sfor(j,1,m) if(f[la][getnum(i,j)]) z[++tt]=f[la][(getnum(i,j))];
      sfor(j,1,tt) f[sg][getnum(i,j)]=z[j];}
   swap(la,sg);return;
  }
inline void R()
  {sfor(i,1,n*m) f[sg][i]=0;
   sfor(i,1,n)
     {int tt=0;
      dfor(j,1,m) if(f[la][getnum(i,j)]) z[++tt]=f[la][(getnum(i,j))];
      sfor(j,1,tt) f[sg][getnum(i,m+1-j)]=z[j];}
   swap(la,sg);return;
  }
inline void del(int x)
  {pre[aft[x]]=pre[x];
   aft[pre[x]]=aft[x];
   return;
  }
int main()
{
int T=read();
while(T--){
la=0,sg=1;
n=read(),m=read();
sfor(i,1,n*m) tto[i]=0;
sfor(i,1,n) {cin>>s[i];s[i]=' '+s[i];}
sfor(i,1,n)
  sfor(j,1,m)
    {if(s[i][j]=='.') f[0][getnum(i,j)]=0;
     else f[0][getnum(i,j)]=s[i][j]-'a'+1;
    }
string cz;
cin>>cz;
int q=cz.size();
cz=' '+cz;
sfor(i,1,q)
  {if(cz[i]=='L') ca[i]=0;
   if(cz[i]=='R') ca[i]=1;
   if(cz[i]=='U') ca[i]=2;
   if(cz[i]=='D') ca[i]=3;
  }
sfor(i,1,q) pre[i]=i-1,aft[i]=i+1;
aft[q]=0;
aft[0]=1;
int now=1;
ca[0]=-114514;//为了防止和L搞混就随便赋一个错乱的值吧awa 
while(now)
  {if(aft[now]==0) break;
   if(aft[now]!=0&&ca[aft[now]]==ca[now]||ca[pre[now]]==ca[aft[now]])
     {del(aft[now]); 
      continue;}
   if(aft[now]!=0&&!(ca[aft[now]]^ca[now]^1))
     {del(now);
      if(pre[now]!=0) now=pre[now];
      else now=aft[now];
      continue;}
   now=aft[now];
  }
int cztt=0;//化简后还剩下多少步 
now=aft[0];
while(now)
  {fi[++cztt]=ca[now];
   now=aft[now];
  }
sfor(i,1,min(2,cztt))
  {if(fi[i]==0) L();
   if(fi[i]==1) R();
   if(fi[i]==2) U();
   if(fi[i]==3) D();
  }
if(cztt>2)
  {int lun=(cztt-2)/4,yu=cztt-2-lun*4;
   if(lun)
     {sfor(i,1,n*m) if(f[la][i]) ans[i]=f[la][i],f[la][i]=i;
      sfor(i,3,6)
        {if(fi[i]==0) L();
         if(fi[i]==1) R();
         if(fi[i]==2) U();
         if(fi[i]==3) D();}
      sfor(i,1,n*m) if(f[la][i]) tto[f[la][i]]=i;
      lun--;//开始走一遍了 
      while(lun)
        {if(lun%2)
          {sfor(i,1,n*m) f[sg][i]=0;
           sfor(i,1,n)
            sfor(j,1,m)
              f[sg][tto[getnum(i,j)]]=f[la][getnum(i,j)];
           swap(la,sg);
          }
         lun/=2;
         sfor(i,1,n*m) cyj[i]=tto[i];
         sfor(i,1,n*m) tto[i]=cyj[cyj[i]];
        }
      sfor(i,1,n*m) if(f[la][i]) f[la][i]=ans[f[la][i]];
     }
   sfor(i,cztt-yu+1,cztt)
     {if(fi[i]==0) L();
      if(fi[i]==1) R();
      if(fi[i]==2) U();
      if(fi[i]==3) D();
     }
  }
sfor(i,1,n)
  {sfor(j,1,m)
   if(f[la][getnum(i,j)]==0) cout<<'.';
   else cout<<(char)('a'-1+f[la][getnum(i,j)]);
   cout<<endl;
  }
sfor(i,1,n*m) f[0][i]=f[1][i]=ans[i]=tto[i]=0;//最后清理一下
}
}