1 条题解

  • 0
    @ 2025-8-24 22:35:25

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Vix
    AFO

    搬运于2025-08-24 22:35:25,当前版本为作者最后更新于2022-09-24 15:47:48,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    原题链接

    题意

    给定只包含 a,b,ca ,b, c 三种字母的两个长度相等的字符串 S,TS, T, 只改变 SS字母位置后得到的新串 SS',使得 i[1,T]\forall i \in [1,|T|], 都满足 SiTi{S'}_ i \ne T_i,求字典序最小的 SS'

    范围:S=T,1S5000|S |= |T|, 1 \le |S| \le 5000

    分析

    首先有且仅有 a,b,ca,b,c 三个字母,又要满足字典序最小,容易想到贪心,因为对于 TT 串中的每一个字母,我们最多只有两个字母可以选择。比如当 Ti=aT_i = a 时,那么 Si=bS'_ i = bcc。现在问题就转化成了在两个字母中选择哪一个,贪心地想,显然选择字典序更小的字母更优,但是原题限制了SS' 是由 SS 变幻而来的,所以 SS 串中 a,b,ca,b,c 的数量是一定的,可能当前选了某个字母后,剩下的字母无法让 SS'TT 每一位都不等。所以正确的策略应该是在保证 SS'TT 每一位都不等的情况下,选择更优的字母。

    怎样保证不等呢?记 SS 中剩余的 a,b,ca,b,c 的数量为 cnta,cntb,cntccnt_a, cnt_b, cnt_cTT 中剩余的 a,b,ca,b,c 的数量为 aima,aimb,aimcaim_a, aim_b, aim_c,恒有 cnta+cntbaimccnt_a + cnt_b \ge aim_c, cnta+cntcaimbcnt_a + cnt_c \ge aim_b, cntb+cntcaimacnt_b + cnt_c \ge aim_a。假如要选择 aa,就要满足 cnta1+cntbaimccnt_a - 1 + cnt_b \ge aim_c 并且 cnta1+cntcaimbcnt_a - 1 + cnt_c \ge aim_bb,cb,c 以此类推,因为只有三个字母,可以直接判断,时间复杂度 O(S)O(|S|)

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 5e3 + 10;
    int n;
    char s[N];
    int cnt[3], aim[3];
    //用 0, 1, 2 代表 a, b, c
    
    int main() {
    	scanf("%d%s", &n, s + 1);
    	for (int i = 1; i <= n; i++)
    		if (s[i] == 'a') cnt[0]++;
    		else if (s[i] == 'b') cnt[1]++;
    		else cnt[2]++;
    	
    	scanf("%s", s + 1);
    	for (int i = 1; i <= n; i++)
    		if (s[i] == 'a') aim[0]++;
    		else if (s[i] == 'b') aim[1]++;
    		else aim[2]++;
    	
    	for (int i = 1; i <= n; i++)
    		if (s[i] == 'a') {
    			aim[0]--;
    			if (cnt[1] && cnt[1] - 1 + cnt[2] >= aim[0] && cnt[1] - 1 + cnt[0] >= aim[2]) cnt[1]--, printf("b");
    			else cnt[2]--, printf("c");
    		} else if (s[i] == 'b') {
    			aim[1]--;
    			if (cnt[0] && cnt[0] - 1 + cnt[1] >= aim[2] && cnt[0] - 1 + cnt[2] >= aim[1]) cnt[0]--, printf("a");
    			else cnt[2]--, printf("c");
    		} else {
    			aim[2]--;
    			if (cnt[0] && cnt[0] - 1 + cnt[1] >= aim[2] && cnt[0] - 1 + cnt[2] >= aim[1]) cnt[0]--, printf("a");
    			else cnt[1]--, printf("b");
    		}
    	return 0;
    }
    

    后话

    建议评橙,考场上很快就想到正解了,不是很难的贪心,听机房的人说可以用爆搜过,tql

    这是本蒟蒻的第一篇题解,有什么错还请dalao指出。

    • 1

    信息

    ID
    7382
    时间
    1000ms
    内存
    64MiB
    难度
    2
    标签
    递交数
    0
    已通过
    0
    上传者