2025.7.9 NOI 模拟赛 题解

T1 变化(change)

题意

对于字符串 \(S\),存在三类操作:删除任意一个为 \(AB,BA,AAAA,BBBB,CDC,DDD\) 的子串,替换子串 \(A\to BBB,B\to AAA,C\to DED,D\to EE,E\to CD,DC\to E\),交换相邻字母满足其中一个为 \(A/B\) 且另一个为 \(C/D/E\),给定 \(s,t\)\(q\) 次询问每次给定 \(s\)\(t\) 的一个区间,判断 \(s\) 的这一区间能否用有限次上述变换变为 \(t\) 的区间,\(|s|,|t|,q\le10^5\)

分析

考虑如何判断 \(s\) 能否转化为 \(t\)

由于 \(AB\to BBBB\to BA\)\(BA\to BBBB\to AB\)\(DC\to E\to CD\)\(CD\to DEDD\to DCDDD\to DC\),以及操作三,可得五种字母可以任意重排

由于 \(A/B\) 只能替换为 \(A/B\)\(C/D/E\) 只能替换为 \(C/D/E\),考虑先将 \(A/B\) 移到字符串前面,\(C/D/E\) 移到字符串后面(由于交换操作可逆,因此对 \(s\)\(t\) 同时操作)

此时前后两段分离

先考虑 \(A/B\) 部分,令 \(x\)\(A\) 的数量,\(y\)\(B\) 的数量,发现 \((x,y)\to (x-1,y+3),\to(x+3,y-1),\to(x-4,y),\to(x,y-4),\to(x-1,y-1)\),发现过程中 \((x-y)\bmod 4\) 不变,且容易构造操作方案使得满足这一条件的变换必然能实现

然后考虑 \(C/D/E\) 部分,显然可以预先把 \(E\) 替换为 \(CD\)(操作同样可逆,因此对 \(s\)\(t\) 都进行变换),令 \(x\)\(C\) 的数量,\(y\)\(D\) 的数量,则 \((x,y)\to(x-2,y-1),\to(x,y-3),\to(x,y+3),\to(x+2,y+1)\),发现 \((x-2y)\bmod 6\) 不变,且容易构造操作方案使得满足这一条件的变换必然能实现

综上,\(s\) 能变换为 \(t\) 当且仅当两个字符串内 \(A/B\) 只差对 \(4\) 同余,且 \(C/D/E\) 的加权和(\(C\) 权值为 \(1\)\(D\) 权值为 \(-2\)\(E\) 权值为 \(-1\))对 \(6\) 同余

容易做到 \(O(|s|+|t|+q)\)

代码:

#include <bits/stdc++.h>
using namespace std;
string s, t; int n, m, q;
int cs[100010], ct[100010];
int ccs[100010], cct[100010];
int main(){
    freopen("change.in", "r", stdin);
    freopen("change.out", "w", stdout);
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> s >> t >> q; n = s.size(), m = t.size(); s = " " + s, t = " " + t;
    for (int i = 1; i <= n; ++i)
        cs[i] = cs[i - 1] + (s[i] == 'A'? 1 : s[i] == 'B'? -1 : 0), ccs[i] = ccs[i - 1] + (s[i] == 'C'? 1 : s[i] == 'D'? -2 : s[i] == 'E'? -1 : 0);
    for (int i = 1; i <= m; ++i)
        ct[i] = ct[i - 1] + (t[i] == 'A'? 1 : t[i] == 'B'? -1 : 0), cct[i] = cct[i - 1] + (t[i] == 'C'? 1 : t[i] == 'D'? -2 : t[i] == 'E'? -1 : 0);
    while (q--){
        int l, r, L, R;
        cin >> l >> r >> L >> R;
        int s = cs[r] - cs[l - 1], t = ct[R] - ct[L - 1];
        if (s - t & 3){cout << "NO" << "\n";continue;}
        s = ccs[r] - ccs[l - 1], t = cct[R] - cct[L - 1];
        if ((s - t) % 6)cout << "NO" << "\n";
        else cout << "YES" << "\n";
    }
    return 0;
}

T2 旅途(travel)\(\quad\) #84. 【UR #7】水题走四方

T3 花园(garden)

比赛结果

\(100+20+20\)\(\text{rk}-2\)

posted @ 2025-07-10 08:10  Hstry  阅读(17)  评论(0)    收藏  举报