2023.11.10联赛 T4题解

题目大意

题目思路

我们考虑分块处理。

我们可以维护一个状态,表示块内每个字母对应的真实字母,因为只有 3 3 3个字母,所以只有 6 6 6种情况。

对于每一个块,我们可以对于每种状态、每种块,预处理出以 A A A或 B B B或 C C C进入出来时是什么字母。

至此,思路就很明了。

修改操作对于散块直接修改,对于整块修改他们的状态。

查询操作对于散块直接跳,对于整块直接用预处理的信息跳即可。

具体实现参考代码。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,q,a[N],b[N],pos[N],posl[N],posr[N],g[N],sum[N][10][5],p[10][5],vis[5][5][5],block=0,tot=0;
char s[N],s1[200+10],s2[200+10];
int read()
{
    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
        s=s*10+(ch-'0'),ch=getchar();
    return s*w;
}
int work(int l,int r,int state,int x)
{
    for(int i=l;i<=r;++i)
    {
        int val=p[state][a[i]];
        if(x%3+1!=val)
            x=val;
    }
    return x;
}
void change(int l,int r,int val1,int val2)
{
    int x=0,y=0;
    for(int i=1;i<=3;++i)
        if(p[g[pos[l]]][i]==val1)
            x=i;    
    for(int i=1;i<=3;++i)
        if(p[g[pos[l]]][i]==val2)
            y=i; 
    for(int i=l;i<=r;++i)
    {
        if(p[g[pos[l]]][a[i]]==val1)
            a[i]=y;
        else if(p[g[pos[l]]][a[i]]==val2)
            a[i]=x;
    }
    for(int i=1;i<=6;++i)   
        for(int j=1;j<=3;++j)
            sum[pos[l]][i][j]=work(posl[pos[l]],posr[pos[r]],i,j);
}   
void update(int l,int r,int val1,int val2)
{
    if(pos[l]==pos[r])
    {
        change(l,r,val1,val2);
        return ;
    }
    change(l,posr[pos[l]],val1,val2);
    for(int i=pos[l]+1;i<=pos[r]-1;++i)
    {
        int c[5];
        for(int j=1;j<=3;++j)
        {
            if(p[g[i]][j]==val1)
                c[j]=val2;
            else if(p[g[i]][j]==val2)
                c[j]=val1;
            else
                c[j]=p[g[i]][j];
        }
        g[i]=vis[c[1]][c[2]][c[3]];
    }
    change(posl[pos[r]],r,val1,val2);
}
int ask(int l,int r,int x)
{
    if(pos[l]==pos[r])
        return work(l,r,g[pos[l]],x);
    x=work(l,posr[pos[l]],g[pos[l]],x);
    for(int i=pos[l]+1;i<=pos[r]-1;++i)
        x=sum[i][g[i]][x];
    x=work(posl[pos[r]],r,g[pos[r]],x);
    return x;
}
int main()
{
    freopen("training.in","r",stdin);
    freopen("training.out","w",stdout);
    n=read(),q=read();
    scanf("%s",s+1);
    block=pow(n,2.0/5.0);
    for(int i=1;i<=n;++i)
        a[i]=s[i]-'A'+1,pos[i]=(i-1)/block+1;
    for(int i=1;i<=pos[n];++i)
    {
        posl[i]=(i-1)*block+1;
        posr[i]=min(i*block,n);
        g[i]=1;
    }
    for(int i=1;i<=3;++i)
        b[i]=i;
    do
    {
        tot++;
        p[tot][1]=b[1];
        p[tot][2]=b[2];
        p[tot][3]=b[3];
        vis[b[1]][b[2]][b[3]]=tot;
        for(int i=1;i<=3;++i)
            for(int j=1;j<=pos[n];++j)
                sum[j][tot][i]=work(posl[j],posr[j],tot,i);
    }while(next_permutation(b+1,b+4));
    while(q--)
    {
        int opt=read(),l=read(),r=read();
        if(opt==0)
        {
            scanf("%s %s",s1+1,s2+1);
            update(l,r,s1[1]-'A'+1,s2[1]-'A'+1);            
        }
        else
        {
            scanf("%s",s1+1);
            printf("%c\n",ask(l,r,s1[1]-'A'+1)+'A'-1);
        }
    }
    return 0;
}
相关推荐
董董灿是个攻城狮11 分钟前
AI视觉连载8:传统 CV 之边缘检测
算法
AI软著研究员7 小时前
程序员必看:软著不是“面子工程”,是代码的“法律保险”
算法
FunnySaltyFish8 小时前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
颜酱8 小时前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法
地平线开发者1 天前
SparseDrive 模型导出与性能优化实战
算法·自动驾驶
董董灿是个攻城狮1 天前
大模型连载2:初步认识 tokenizer 的过程
算法
地平线开发者1 天前
地平线 VP 接口工程实践(一):hbVPRoiResize 接口功能、使用约束与典型问题总结
算法·自动驾驶
罗西的思考1 天前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习
HXhlx1 天前
CART决策树基本原理
算法·机器学习
Wect1 天前
LeetCode 210. 课程表 II 题解:Kahn算法+DFS 双解法精讲
前端·算法·typescript