update
This commit is contained in:
parent
882ec2fbea
commit
f485391c43
3
src/7/17/Box0.in
Normal file
3
src/7/17/Box0.in
Normal file
@ -0,0 +1,3 @@
|
||||
5
|
||||
AbCDx
|
||||
dECba
|
1
src/7/17/Box0.out
Normal file
1
src/7/17/Box0.out
Normal file
@ -0,0 +1 @@
|
||||
15
|
3
src/7/17/Box1.in
Normal file
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
1
src/7/17/Box1.out
Normal file
@ -0,0 +1 @@
|
||||
698813
|
3
src/7/17/Box2.in
Normal file
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
1
src/7/17/Box2.out
Normal file
@ -0,0 +1 @@
|
||||
699307
|
121
src/7/17/T634195.cpp
Normal file
121
src/7/17/T634195.cpp
Normal 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
104
src/7/17/T634195.md
Normal 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
3
src/7/17/T634197.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
int main(){
|
||||
|
||||
}
|
73
src/7/17/T634198.cpp
Normal file
73
src/7/17/T634198.cpp
Normal 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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
初始化:首先,初始化一个数组arr,其中arr[i] = i,表示初始状态下第i天的温度是i。
|
||||
模拟交换:读取每次交换操作,如果交换的两个位置都在1到100,000的范围内,则交换数组中这两个位置的值。
|
||||
计算逆序对:
|
||||
使用树状数组(Fenw)来高效计算逆序对数量。
|
||||
遍历数组,对于每个元素arr[j],查询树状数组中值大于arr[j]的元素数量(这些元素位于j之前),并将这个数量累加到答案中。
|
||||
将当前元素arr[j]插入树状数组,以便后续查询。
|
||||
输出结果:最终累加的逆序对数量即为答案。
|
||||
|
||||
*/
|
87
src/7/17/T634198.md
Normal file
87
src/7/17/T634198.md
Normal 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%的数据规模,通过树状数据结构优化了逆序对的计算过程,确保在合理的时间和空间复杂度内得到结果。
|
Loading…
Reference in New Issue
Block a user