This commit is contained in:
Zengtudor 2025-07-17 10:21:36 +08:00
parent 882ec2fbea
commit f485391c43
11 changed files with 400 additions and 0 deletions

3
src/7/17/Box0.in Normal file
View File

@ -0,0 +1,3 @@
5
AbCDx
dECba

1
src/7/17/Box0.out Normal file
View File

@ -0,0 +1 @@
15

3
src/7/17/Box1.in Normal file

File diff suppressed because one or more lines are too long

1
src/7/17/Box1.out Normal file
View File

@ -0,0 +1 @@
698813

3
src/7/17/Box2.in Normal file

File diff suppressed because one or more lines are too long

1
src/7/17/Box2.out Normal file
View File

@ -0,0 +1 @@
699307

121
src/7/17/T634195.cpp Normal file
View File

@ -0,0 +1,121 @@
// #include <cstdint>
// #include <iostream>
// #include <string>
// using ll = int64_t;
// ll n,ans{};
// std::string s1,s2;
// bool isBig(char c){
// return 'A'<=c&&c<='Z';
// }
// void swapBS(char &c){
// if(isBig(c)){
// c=c-'A'+'a';
// }else{
// c=c-'a'+'A';
// }
// }
// ll rn(ll idx){
// ll ans{};
// if(s2[idx]>=s1[idx]){
// ans=s2[idx]-s1[idx];
// }else{
// }
// // return
// }
// int main(){
// std::cin>>n;
// std::cin>>s1>>s2;
// s1=' '+s1;
// s2=' '+s2;
// for(ll i=s1.size()-1;i>=1;i--){
// if(isBig(s1[i])!=isBig(s2[i]))ans++;
// swapBS(s1[i]);
// }
// }
// /*
// 1. 改变大小写
// 2. 前后移动字典序
// 1. 如果向右越界那么前面一个字母的字典序+1
// 2. 向左则反之
// 3. 第一位不用考虑这些
// 4. 类似于26进制
// */
#include <cstdint>
#include<iostream>
#include <vector>
#include <cctype>
using namespace std;
using ll = int64_t;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
string s1, s2;
cin >> s1 >> s2;
ll co = 0;
vector<int> A(n), B(n);
for (int i = 0; i < n; i++) {
if (isupper(s1[i])) {
A[i] = s1[i] - 'A';
} else {
A[i] = s1[i] - 'a';
}
if (isupper(s2[i])) {
B[i] = s2[i] - 'A';
} else {
B[i] = s2[i] - 'a';
}
bool s1_upper = isupper(s1[i]);
bool s2_upper = isupper(s2[i]);
if (s1_upper != s2_upper) {
co++;
}
}
vector<ll> diff(n);
for (int i = 0; i < n; i++) {
diff[i] = B[i] - A[i];
}
for (int i = n - 1; i >= 1; i--) {
ll x = diff[i];
ll temp = x + 12;
ll q;
if (temp >= 0) {
q = temp / 26;
} else {
q = temp / 26;
if (temp % 26 != 0) {
q--;
}
}
ll r = x - 26 * q;
diff[i] = r;
diff[i - 1] += q;
}
ll mo = 0;
for (int i = 0; i < n; i++) {
mo += abs(diff[i]);
}
ll ans = mo + co;
cout << ans << endl;
return 0;
}

104
src/7/17/T634195.md Normal file
View File

@ -0,0 +1,104 @@
为了解决这个问题,我们需要将上排字符串通过最少的操作转换为下排字符串。操作包括改变字母的大小写或按字典序向前/向后移动字母,其中移动字母可能引发进位或退位传播。我们的目标是计算最小操作次数。
### 方法思路
1. **问题分析**
- **大小写操作**独立于移动操作每个位置的大小写转换只需1次操作且不传播。
- **字母移动操作**每次移动一个字母可能引发向左的进位或退位传播相当于在26进制数上进行加减操作。每个位置的净改变量可以通过调整系数来最小化总操作次数。
2. **关键思路**
- **字母值转换**将每个字符映射到0-25的整数忽略大小写
- **大小写操作计数**:统计初始和目标字符串大小写不同的位置数。
- **差分数组**:计算目标字母值减去初始字母值的差分数组。
- **进位调整**:从右向左调整差分数组,使每个位置的改变量落在[-12, 13]区间内,以最小化操作次数。调整过程中,进位或退位会向左传播。
- **总操作数**:移动操作数为调整后差分数组各元素绝对值之和,加上大小写操作数。
### 解决代码
```cpp
#include <iostream>
#include <vector>
#include <cctype>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
string s1, s2;
cin >> s1 >> s2;
long long case_ops = 0;
vector<int> A(n), B(n);
for (int i = 0; i < n; i++) {
if (isupper(s1[i])) {
A[i] = s1[i] - 'A';
} else {
A[i] = s1[i] - 'a';
}
if (isupper(s2[i])) {
B[i] = s2[i] - 'A';
} else {
B[i] = s2[i] - 'a';
}
bool s1_upper = isupper(s1[i]);
bool s2_upper = isupper(s2[i]);
if (s1_upper != s2_upper) {
case_ops++;
}
}
vector<long long> diff(n);
for (int i = 0; i < n; i++) {
diff[i] = B[i] - A[i];
}
for (int i = n - 1; i >= 1; i--) {
long long x = diff[i];
long long temp = x + 12;
long long q;
if (temp >= 0) {
q = temp / 26;
} else {
q = temp / 26;
if (temp % 26 != 0) {
q--;
}
}
long long r = x - 26 * q;
diff[i] = r;
diff[i - 1] += q;
}
long long move_ops = 0;
for (int i = 0; i < n; i++) {
move_ops += abs(diff[i]);
}
long long ans = move_ops + case_ops;
cout << ans << endl;
return 0;
}
```
### 代码解释
1. **输入处理**
- 读取字符串长度 `n` 和上下排字符串 `s1`、`s2`。
2. **大小写操作计数**
- 遍历每个字符将字母转换为0-25的整数值忽略大小写并记录大小写是否相同。若不同则增加 `case_ops`
3. **差分数组初始化**
- 计算目标字母值与初始字母值的差值,存入 `diff` 数组。
4. **进位调整**
- 从右向左(低位到高位)调整 `diff` 数组。对每个位置计算调整值 `q` 和余数 `r`,确保 `r` 在[-12, 13]区间内,并将进位 `q` 传递到左侧位置。
5. **移动操作计数**
- 调整后,`diff` 数组各元素的绝对值之和即为移动操作次数 `move_ops`
6. **输出结果**
- 总操作数为 `move_ops``case_ops` 之和。
这种方法高效地处理了字母移动引发的进位传播,并通过调整差分数组最小化操作次数,结合独立的大小写转换操作,得到最优解。

3
src/7/17/T634197.cpp Normal file
View File

@ -0,0 +1,3 @@
int main(){
}

73
src/7/17/T634198.cpp Normal file
View File

@ -0,0 +1,73 @@
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAX_N = 100000;
struct Sm {
vector<int> tree;
int n;
Sm(int size) {
n = size;
tree.assign(n + 1, 0);
}
void update(int i, int v) {
while (i <= n) {
tree[i] += v;
i += i & -i;
}
}
int query(int i) {
int sum = 0;
while (i) {
sum += tree[i];
i -= i & -i;
}
return sum;
}
int query(int l, int r) {
if (l > r) return 0;
return query(r) - query(l - 1);
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int k;
cin >> k;
vector<int> arr(MAX_N + 1);
for (int i = 1; i <= MAX_N; i++) {
arr[i] = i;
}
for (int i = 0; i < k; i++) {
int x, y;
cin >> x >> y;
if (x <= MAX_N && y <= MAX_N) {
swap(arr[x], arr[y]);
}
}
Sm sm(MAX_N);
long long ans = 0;
for (int j = 1; j <= MAX_N; j++) {
if (arr[j] < MAX_N) {
ans += sm.query(arr[j] + 1, MAX_N);
}
sm.update(arr[j], 1);
}
cout << ans << endl;
return 0;
}
/*
arrarr[i] = ii天的温度是i
1100,000
使Fenw
arr[j]arr[j]j之前
arr[j]便
*/

87
src/7/17/T634198.md Normal file
View File

@ -0,0 +1,87 @@
为了解决这个问题我们需要计算在进行了k次温度交换操作后整个夏天中所有满足条件即前面的天比后面的天热即 \(i < j\) \(D_i > D_j\))的天数对的数量。由于数据规模较大,我们采用以下策略:
### 方法思路
1. **问题分析**初始时第i天的温度就是i即 \(D_i = i\)),因此初始状态下没有逆序对(因为对于任意 \(i < j\) \(D_i < D_j\))。每次交换操作会交换两天的温度从而可能产生新的逆序对或消除原有的逆序对
2. **关键观察**对于50%的数据,交换的位置 \(x_i\) 和 \(y_i\) 均不超过100,000。因此我们只需要考虑位置在1到100,000之间的天因为位置超过100,000的天未被交换且其温度等于位置值不会与任何天构成逆序对。
3. **算法选择**
- **模拟交换**首先初始化一个数组其中第i个元素的值为i。然后对每次交换操作交换数组中对应位置的值。
- **计算逆序对**使用树状数组Fenwick Tree来高效计算最终数组中的逆序对数量。具体方法是从左到右遍历数组对于每个元素查询树状数组中大于当前元素值的元素数量这些元素就是位于当前元素之前且值大于当前元素的元素即构成逆序对。
4. **复杂度分析**
- **时间复杂度**O(k + N log N)其中k是交换次数N是位置上限100,000。模拟交换操作需要O(k)时间计算逆序对需要O(N log N)时间。
- **空间复杂度**O(N),用于存储数组和树状数组。
### 解决代码
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAX_N = 100000;
struct Fenw {
vector<int> tree;
int n;
Fenw(int size) {
n = size;
tree.assign(n + 1, 0);
}
void update(int i, int v) {
while (i <= n) {
tree[i] += v;
i += i & -i;
}
}
int query(int i) {
int sum = 0;
while (i) {
sum += tree[i];
i -= i & -i;
}
return sum;
}
int query(int l, int r) {
if (l > r) return 0;
return query(r) - query(l - 1);
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int k;
cin >> k;
vector<int> arr(MAX_N + 1);
for (int i = 1; i <= MAX_N; i++) {
arr[i] = i;
}
for (int i = 0; i < k; i++) {
int x, y;
cin >> x >> y;
if (x <= MAX_N && y <= MAX_N) {
swap(arr[x], arr[y]);
}
}
Fenw fenw(MAX_N);
long long ans = 0;
for (int j = 1; j <= MAX_N; j++) {
if (arr[j] < MAX_N) {
ans += fenw.query(arr[j] + 1, MAX_N);
}
fenw.update(arr[j], 1);
}
cout << ans << endl;
return 0;
}
```
### 代码解释
1. **初始化**:首先,初始化一个数组`arr`,其中`arr[i] = i`表示初始状态下第i天的温度是i。
2. **模拟交换**读取每次交换操作如果交换的两个位置都在1到100,000的范围内则交换数组中这两个位置的值。
3. **计算逆序对**
- 使用树状数组(`Fenw`)来高效计算逆序对数量。
- 遍历数组,对于每个元素`arr[j]`,查询树状数组中值大于`arr[j]`的元素数量(这些元素位于`j`之前),并将这个数量累加到答案中。
- 将当前元素`arr[j]`插入树状数组,以便后续查询。
4. **输出结果**:最终累加的逆序对数量即为答案。
这种方法高效地处理了50%的数据规模,通过树状数据结构优化了逆序对的计算过程,确保在合理的时间和空间复杂度内得到结果。