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;
}
posted @ 2025-05-19 15:28  渝州炒鸡舞帝神兽大王  阅读(27)  评论(0)    收藏  举报