• [CF1149B] Three Religions


    Description

    给定长度为 (n) 的母串和三个子串 (s_1,s_2,s_3)。初始时子串均为空。

    (q) 次询问。你需要支持两种操作:向某个子串末尾添加一个字母,或者删去某个子串末尾的字母。

    在每次操作后,你需要回答,是否能从母串中分离出三个不相交的子序列,满足这三个子序列恰好是 (s_1,s_2,s_3)

    在任意时刻,(s_1,s_2,s_3) 的长度均不会超过 (250)

    (1 le n le 10^5) , (1le q le 10^3)

    Solution

    (f[i][j][k]) 表示三个子串分别匹配到了第 (i,j,k) 个字符,在母串中推进的最短距离

    (g[i][c]) 表示 (S[i..n]) 内字符 (c) 第一次出现的位置

    [f[i][j][k]=left{ egin{aligned} & g[f[i-1][j][k]+1][s_1[i]] \ & g[f[i][j-1][k]+1][s_2[j]] \ & g[f[i][j][k-1]+1][s_3[k]] end{aligned} ight. ]

    初始条件 (f[0][0][0]=0),其余初值设为 (+infty)

    对于插入操作,暴力计算即可,每次 (O(l^2))

    对于删除操作,减小串长即可

    对于询问,比较 (f[l_1][l_2][l_3]) 是否 (le n) 即可

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 100005;
    
    char s[N],s1[N],s2[N],s3[N];
    int n,l1,l2,l3,q,id,g[N][26],f[255][255][255];
    char op,tmp;
    
    void presolve()
    {
        for(int i=0;i<26;i++)
        {
            int ch='a'+i;
    
            vector <int> vec;
            for(int j=1;j<=n;j++) if(s[j]==ch) vec.push_back(j);
    
            int pos=1;
            for(auto now:vec)
            {
                for(int j=pos;j<=now;j++) g[j][i]=now;
                pos=now+1;
            }
            for(int j=pos;j<=n+2;j++) g[j][i]=n+1;
        }
    }
    
    void dp1(int i)
    {
        for(int j=0;j<=l2;j++)
        {
            for(int k=0;k<=l3;k++)
            {
                int tmp=1e9;
                if(i) tmp=min(tmp, g[f[i-1][j][k]+1][s1[i]-'a']);
                if(j) tmp=min(tmp, g[f[i][j-1][k]+1][s2[j]-'a']);
                if(k) tmp=min(tmp, g[f[i][j][k-1]+1][s3[k]-'a']);
                f[i][j][k]=tmp;
            }
        }
    }
    
    void dp2(int j)
    {
        for(int i=0;i<=l1;i++)
        {
            for(int k=0;k<=l3;k++)
            {
                int tmp=1e9;
                if(i) tmp=min(tmp, g[f[i-1][j][k]+1][s1[i]-'a']);
                if(j) tmp=min(tmp, g[f[i][j-1][k]+1][s2[j]-'a']);
                if(k) tmp=min(tmp, g[f[i][j][k-1]+1][s3[k]-'a']);
                f[i][j][k]=tmp;
            }
        }
    }
    
    void dp3(int k)
    {
        for(int i=0;i<=l1;i++)
        {
            for(int j=0;j<=l2;j++)
            {
                int tmp=1e9;
                if(i) tmp=min(tmp, g[f[i-1][j][k]+1][s1[i]-'a']);
                if(j) tmp=min(tmp, g[f[i][j-1][k]+1][s2[j]-'a']);
                if(k) tmp=min(tmp, g[f[i][j][k-1]+1][s3[k]-'a']);
                f[i][j][k]=tmp;
            }
        }
    }
    
    void cl1(int i)
    {
        for(int j=0;j<=l2;j++)
        {
            for(int k=0;k<=l3;k++)
            {
                f[i][j][k]=n+1;
            }
        }
    }
    
    void cl2(int j)
    {
        for(int i=0;i<=l1;i++)
        {
            for(int k=0;k<=l3;k++)
            {
                f[i][j][k]=n+1;
            }
        }
    }
    
    void cl3(int k)
    {
        for(int i=0;i<=l1;i++)
        {
            for(int j=0;j<=l2;j++)
            {
                f[i][j][k]=n+1;
            }
        }
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n>>q>>s+1;
    
        for(int i=0;i<=254;i++)
        {
            for(int j=0;j<=254;j++)
            {
                for(int k=0;k<=254;k++)
                {
                    f[i][j][k]=n+1;
                }
            }
        }
    
        presolve();
    
        f[0][0][0]=0;
    
        for(int i=1;i<=q;i++)
        {
            cin>>op;
            if(op=='+')
            {
                cin>>id>>tmp;
                if(id==1) s1[++l1]=tmp, dp1(l1);
                if(id==2) s2[++l2]=tmp, dp2(l2);
                if(id==3) s3[++l3]=tmp, dp3(l3);
            }
            else
            {
                cin>>id;
                if(id==1) cl1(l1), --l1;
                if(id==2) cl2(l2), --l2;
                if(id==3) cl3(l3), --l3;
            }
            cout<<(f[l1][l2][l3]<=n ? "YES" : "NO")<<endl;
        }
    }
    
    
  • 相关阅读:
    poj 2528 Mayor's posters (线段树+离散化)
    poj 1201 Intervals (差分约束)
    hdu 4109 Instrction Arrangement (差分约束)
    poj 1195 Mobile phones (二维 树状数组)
    poj 2983 Is the Information Reliable? (差分约束)
    树状数组 讲解
    poj 2828 Buy Tickets (线段树)
    hdu 1166 敌兵布阵 (树状数组)
    Ubuntu网络配置
    Button控制窗体变量(开关控制灯的状态)
  • 原文地址:https://www.cnblogs.com/mollnn/p/13329716.html
Copyright © 2020-2023  润新知