来吧,兄弟们,再来篇题解,其实也不是题解,是我自己的思路/心得/体会
Update Queries
题面翻译
题目翻译
一共 $t$ 组数据,每组数据给定长度为 $n$ 的字符串 $s$,长度为 $m$ 的 $ind$ 数组和字符串 $c$。
你可以任意安排 $ind$ 数组和字符串 $c$ 的顺序,并按照此顺序对字符串 $s$ 进行 $m$ 次操作:对于第 $i$ 次操作,将 $s_{ind_i}$ 的值更改为 $c_i$。要求经过 $m$ 次操作后的字符串 $s$ 的字典序最小,输出这个 $s$。
数据范围及约定
- $1 \le n,m \le 10^5$;
- 对于 $\forall i \in [1,m]$,有 $1 \le ind_i \le n$;
- $1 \le t \le 10^4$;
- $1 \le \sum n,\sum m \le 2 \times 10^5$;
- 保证字符串 $s$ 和字符串 $c$ 仅包含小写字母。
题目描述
Let's consider the following simple problem. You are given a string $ s $ of length $ n $ , consisting of lowercase Latin letters, as well as an array of indices $ ind $ of length $ m $ ( $ 1 \leq ind_i \leq n $ ) and a string $ c $ of length $ m $ , consisting of lowercase Latin letters. Then, in order, you perform the update operations, namely, during the $ i $ -th operation, you set $ s_{ind_i} = c_i $ . Note that you perform all $ m $ operations from the first to the last.
Of course, if you change the order of indices in the array $ ind $ and/or the order of letters in the string $ c $ , you can get different results. Find the lexicographically smallest string $ s $ that can be obtained after $ m $ update operations, if you can rearrange the indices in the array $ ind $ and the letters in the string $ c $ as you like.
A string $ a $ is lexicographically less than a string $ b $ if and only if one of the following conditions is met:
- $ a $ is a prefix of $ b $ , but $ a \neq b $ ;
- in the first position where $ a $ and $ b $ differ, the symbol in string $ a $ is earlier in the alphabet than the corresponding symbol in string $ b $ .
输入格式
Each test consists of several sets of input data. The first line contains a single integer $ t $ ( $ 1 \leq t \leq 10^4 $ ) — the number of sets of input data. Then follows their description.
The first line of each set of input data contains two integers $ n $ and $ m $ ( $ 1 \leq n, m \leq 10^5 $ ) — the length of the string $ s $ and the number of updates.
The second line of each set of input data contains a string $ s $ of length $ n $ , consisting of lowercase Latin letters.
The third line of each set of input data contains $ m $ integers $ ind_1, ind_2, \ldots, ind_m $ ( $ 1 \leq ind_i \leq n $ ) — the array of indices $ ind $ .
The fourth line of each set of input data contains a string $ c $ of length $ m $ , consisting of lowercase Latin letters.
It is guaranteed that the sum of $ n $ over all sets of input data does not exceed $ 2 \cdot 10^5 $ . Similarly, the sum of $ m $ over all sets of input data does not exceed $ 2 \cdot 10^5 $ .
输出格式
For each set of input data, output the lexicographically smallest string $ s $ that can be obtained by rearranging the indices in the array $ ind $ and the letters in the string $ c $ as you like.
样例 #1
样例输入 #1
4
1 2
a
1 1
cb
4 4
meow
1 2 1 4
zcwz
7 4
abacaba
1 3 5 7
damn
7 10
traktor
7 6 5 4 3 2 1 6 4 2
codeforces
样例输出 #1
b
cwoz
abdcmbn
ccdeefo
提示
In the first set of input data, you can leave the array $ ind $ and the string $ c $ unchanged and simply perform all operations in that order.
In the second set of input data, you can set the array $ ind = [1, 1, 4, 2] $ and $ c = $ "zczw". Then the string $ s $ will change as follows: $ meow \rightarrow zeow \rightarrow ceow \rightarrow ceoz \rightarrow cwoz $ .
In the third set of input data, you can leave the array $ ind $ unchanged and set $ c = $ "admn". Then the string $ s $ will change as follows: $ abacaba \rightarrow abacaba \rightarrow abdcaba \rightarrow abdcmba \rightarrow abdcmbn $ .
我们解决这个题,首先要明白,什么是字典序。假设,从1到5,5个数。
最小情况就是1,2,3,4,5
最大就是5,4,3,2,1
序列相比是逐位对比的,从第一位开始,谁大谁的字典序就更大,如果一样就向后推,特殊的,类似这种,1比12的字典序要小。
结合输入分析题目,题目意思是给我们一个已知的序列s。我们要将ind数组结合字符串C按顺序修改字符串s并使其字典序最小。但我们可以任意将ind数组与c结合
如
4 4
meow
1 2 1 4
zcwz
原s数组是m e o w,c字符串是z c w z ,修改结果为c w o z。
如要让字符串的字典序最小,我们就需要让他按升序排列,在原序列的基础上对其进行修改,不仅是字符串需要升序,我们的修改也需要升序,这样的话,就可以最大限度的保证字典序最小。
特殊情况,例如这里面的1 1,有重复的,也就是说,这个值会被后来的值进行覆盖,我们可以利用这一点,如果有重复的修改点位,就将最大的(字典序)字母插入这里,后续被其他的所替代,代码上,我们可以直接删除重复的一步,并将最大字典序的字母删除。
所以该题的重点就是,去重以及排序.
代码如下#include
include<string.h>
include
include
using namespace std;
const int damn = 1e5 + 5;
char c[damn];
int num[damn];
char ind[damn];
int main()
{
int t;
cin >> t;
while (t--)
{
int n, m;
cin >> n >> m;
scanf("%s", c + 1);
for (int i = 1; i <= m; i++)
scanf("%d", &num[i]);
scanf("%s", ind + 1);
sort(ind + 1, ind + m + 1);
sort(num + 1, num + m + 1);
int cnt = 0;
for (int i = 1; i <= m; i++)
{
if (num[i] != num[i - 1])
{
c[num[i]] = ind[++cnt];
}
}
printf("%s\n", c + 1);
}
return 0;
}