CF1996C题解
C.Sort
题目描述
You are given two strings and bof length n. Then, you are (forced against your will) to answer q queries.
For each query, you are given a range bounded by l and r. In one operation, you can choose an integer i (l≤i≤r) and set ai=x where x is any character you desire. Output the minimum number of operations you must perform such that sorted(a[l..r])=sorted(b[l..r]). The operations you perform on one query does not affect other queries.
For an arbitrary string c, sorted(c[l..r]) denotes the substring consisting of characters cl,cl+1,...,cr sorted in lexicographical order.
Input:
The first line contains t(1≤t≤1000) – the number of test cases.
The first line of each test case contains two integers n
and q(1≤n,q≤2⋅1e5) – the length of both strings and the number of queries.
The following line contains a of length n. It is guaranteed a only contains lowercase latin letters.
The following line contains b of length n. It is guaranteed b only contains lowercase latin letters.
The following q lines contain two integers l and r (1≤l≤r≤n) – the range of the query.
It is guaranteed the sum of n and q over all test cases does not exceed 2⋅1e5.
Output:
For each query, output an integer, the minimum number of operations you need to perform in a new line.
题目概述
给定两个长度为 n 的字符串 a 和 b,以及 q 个查询,每次查询一个区间 [l, r],要求计算将 a[l..r] 变换为 b[l..r] 所需的最小操作次数。每次操作可以将一个字符替换为另一个字符。
解题思路
对于任意区间[l,r],只需要比较这两个子串中各个字母的出现次数是否一致:
- 如果一个字母在a[l,,,r]中出现了5次,在b[l,,,r]中出现了2次
- 就说明有3个多余或缺失的字母
- 所以至少需要进行3次字符替换才能对齐这些字母的数量
为了高效统计任意区间[l,r]中各字母出现次数,我们对两个字符串分别建立前缀和数组
vector<vector<int>> pre1(n + 1, vector<int>(26, 0)); // 统计a的前缀
vector<vector<int>> pre2(n + 1, vector<int>(26, 0)); // 统计b的前缀
- pre1[i][j]表示:字符串a的前i个字符中,字母‘a’+j出现了多少次
- pre2同理表示b的信息
- 通过以下公式能够快速得到区间[l,r]中'a'+j字母出现的次数
int n1 = pre1[r][i] - pre1[l - 1][i];
对于每一次的查询[l,r]:
- 对于所有26个字母,分别计算它们在a[l,r]和b[l,r]中出现的次数之差
- 将差值的绝对值累加起来(比如:a中有5个某字母,b中有3个,那差值就为2)
- 由于一个修改可以同时修正 a 的一个多余和 b 的一个缺少,所以最终答案是:总差值 / 2
AC Code
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
void solve()
{
int n, q;
std::cin >> n >> q;
std::string a, b;
std::cin >> a >> b;
a = ' ' + a, b = ' ' + b;
std::vector<std::vector<int>> pre1(n + 1, std::vector<int>(26, 0));
std::vector<std::vector<int>> pre2(n + 1, std::vector<int>(26, 0));
for (int i = 1; i <= n; ++i)
{
pre1[i][a[i] - 'a']++;
pre2[i][b[i] - 'a']++;
for (int j = 0; j < 26; ++j)
{
pre1[i][j] += pre1[i - 1][j];
pre2[i][j] += pre2[i - 1][j];
}
}
while (q--)
{
int l, r;
std::cin >> l >> r;
int num = 0;
for (int i = 0; i < 26; ++i)
{
int n1 = pre1[r][i] - pre1[l - 1][i];
int n2 = pre2[r][i] - pre2[l - 1][i];
num += std::abs(n1 - n2);
}
std::cout << num / 2 << endl;
}
}
signed main()
{
std::ios_base::sync_with_stdio(0);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int _;
//_=1;
std::cin >> _;
while (_--)
{
solve();
}
return 0;
}

浙公网安备 33010602011771号