1 条题解

  • 0
    @ 2026-4-30 15:29:49

    首先手玩样例,发现怎么做资源库最多都只有九个。

    如何证明?我们把 J,O,I 分别设为 0,1,2,容易得到每一位上 xxyy 变换后即为 3xymod33-x-y \mod 3,这样的转换显然只有 $x,y,z,x\textrm{ cross }y,y\textrm{ cross }z,z\textrm{ cross }x,x\textrm{ cross }(y\textrm{ cross }z),y\textrm{ cross }(z\textrm{ cross }x),z\textrm{ cross }(x\textrm{ cross }y)$。

    于是我们可以一开始把这九个字符串哈希出来,之后给出的字符串用线段树维护哈希值,判断是否与前面的九个值相等即可。

    #include<iostream>
    #include<cstdio>
    #include<unordered_map>
    #define int long long
    using namespace std;
    const int mod=1000000007,mod2=998244353;
    struct node{
        int sum1,sum2,lz;
    }tr[800005];
    int n,q,v[1145],f[200005],pre[200005],f2[200005],pre2[200005];
    string str[15],s;
    unordered_map<int,int>mp,mp2;
    string cr(string x,string y){
        string z="";
        for(int i=0;i<n;i++){
            int w=v[x[i]],u=v[y[i]];
            int k=(3-(w+u)%3)%3;
            if(k==0) z+="J";
            else if(k==1) z+="O";
            else z+="I";
        }
        return z;
    }
    int gethash(string x){
        int sum=0;
        for(int i=0;i<n;i++) sum=sum+(v[x[i]]+1)*f[i]%mod,sum%=mod;
        return sum;
    }
    int gethash2(string x){
        int sum=0;
        for(int i=0;i<n;i++) sum=sum+(v[x[i]]+1)*f2[i]%mod2,sum%=mod2;
        return sum;
    }
    void pushup(int k,int l,int r,int mid){
        tr[k].sum1=tr[k*2].sum1+tr[k*2+1].sum1*f[mid-l+1]%mod;tr[k].sum1%=mod;
        tr[k].sum2=tr[k*2].sum2+tr[k*2+1].sum2*f2[mid-l+1]%mod2;tr[k].sum2%=mod2;
    }
    void pushdown(int k,int l,int r,int mid){
        if(tr[k].lz){
            tr[k*2].sum1=pre[mid-l]*tr[k].lz%mod;tr[k*2].lz=tr[k].lz;
            tr[k*2+1].sum1=pre[r-mid-1]*tr[k].lz%mod;tr[k*2+1].lz=tr[k].lz;
            tr[k*2].sum2=pre2[mid-l]*tr[k].lz%mod2;tr[k*2].lz=tr[k].lz;
            tr[k*2+1].sum2=pre2[r-mid-1]*tr[k].lz%mod2;tr[k*2+1].lz=tr[k].lz;
            tr[k].lz=0;
        }
    }
    void build(int k,int l,int r){
        if(l==r){
            tr[k].sum1=v[s[l]]+1;
            tr[k].sum2=v[s[l]]+1;
            return;
        }
        int mid=(l+r)/2;
        build(k*2,l,mid);build(k*2+1,mid+1,r);
        pushup(k,l,r,mid);
    }
    void update(int k,int l,int r,int x,int y,int op){
        if(r<x||l>y) return;
        if(x<=l&&r<=y){
            tr[k].sum1=pre[r-l+1-1]*op%mod;
            tr[k].sum2=pre2[r-l+1-1]*op%mod2;
            tr[k].lz=op;
            return;
        }
        int mid=(l+r)/2;
        pushdown(k,l,r,mid);
        update(k*2,l,mid,x,y,op);
        update(k*2+1,mid+1,r,x,y,op);
        pushup(k,l,r,mid);
    }
    signed main(){
        cin>>n>>str[1]>>str[2]>>str[3];v['J']=0,v['O']=1,v['I']=2;
        f[0]=1;for(int i=1;i<=n;i++) f[i]=f[i-1]*233%mod;
        for(int i=0;i<=n;i++) pre[i]=f[i]+pre[i-1],pre[i]%=mod;
        f2[0]=1;for(int i=1;i<=n;i++) f2[i]=f2[i-1]*131%mod2;
        for(int i=0;i<=n;i++) pre2[i]=f2[i]+pre2[i-1],pre2[i]%=mod2;
        str[4]=cr(str[1],str[2]);str[5]=cr(str[2],str[3]);str[6]=cr(str[3],str[1]);
        str[7]=cr(str[4],str[5]);str[8]=cr(str[5],str[6]);str[9]=cr(str[6],str[4]);
        for(int i=1;i<=9;i++) mp[gethash(str[i])]++,mp2[gethash2(str[i])]++/*,cout<<str[i]<<' '<<gethash(str[i])<<endl*/;
        cin>>q>>s;s=" "+s;
        build(1,1,n);
        // cout<<tr[1].sum<<endl;
        if(mp.count(tr[1].sum1)&&mp2.count(tr[1].sum2)) cout<<"Yes\n";
        else cout<<"No\n";
        while(q--){
            int l,r,x;char op;
            cin>>l>>r>>op;
            x=v[op]+1;update(1,1,n,l,r,x);
            // cout<<tr[1].sum<<endl;
            if(mp.count(tr[1].sum1)&&mp2.count(tr[1].sum2)) cout<<"Yes\n";
            else cout<<"No\n";
        }
        return 0;
    }
    
    • 1

    信息

    ID
    10163
    时间
    5000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者