难以理解某些人解决IOI问题的源代码
Difficulty understanding someones source code to a solution of an IOI problem
以下是问题的链接:https://ioi2019.az/source/Tasks/Day1/Shoes/NGA.pdf
以下是关于问题状态的简短解释t:
您将得到一个范围为1≤n≤1e5的整数n,它将表示数组中正整数的数量,以及数组中负整数的数量(因此数组的总大小将为 2n这个问题希望您找到数组中所需的最小交换次数,以便一个数字的负值和该负数的绝对值彼此相邻(使得-x在x的右边( 示例: n=2; 输入的数组={2,1,-1,-2} 最少操作次数为四次: 2,1,-1,-2:0掉期 2,-1,1,-2:1交换(交换1和-1( 2,-1,-2,2:2掉期(掉期1和-2( 2,-2,-1,1:3掉期(交换-1和-2( -2,2,-1,1:4掉期(掉期2和-2( 最后的答案是四。 另一个例子: 输入的数组={-2,2,2,-2,-2,2} 最低互换额为1。因为我们可以交换索引2和3处的元素。 最终阵列:{-2,2,-2,2和-2,2} 在回答这个问题时,我得到了错误的答案,我决定查看github上的一些源代码。 这是源代码: 然而,我认为我对这个代码理解得不太好。 我理解BIT中添加和查询的功能,我只是对代码的注释一直到底部感到困惑。我不明白它的作用和目的。 有人能浏览一下这个代码在做什么吗?或者就我应该如何正确有效地#include "shoes.h"
#include <bits/stdc++.h>
#define sz(v) ((int)(v).size())
using namespace std;
using lint = long long;
using pi = pair<int, int>;
const int MAXN = 200005;
struct bit{
int tree[MAXN];
void add(int x, int v){
for(int i=x; i<MAXN; i+=i&-i) tree[i] += v;
}
int query(int x){
int ret = 0;
for(int i=x; i; i-=i&-i) ret += tree[i];
return ret;
}
}bit;
lint count_swaps(vector<int> s) {
int n = sz(s) / 2;
lint ret = 0;
vector<pi> v;
vector<pi> ord[MAXN];
for(int i=0; i<sz(s); i++){
ord[abs(s[i])].emplace_back(s[i], i);
}
for(int i=1; i<=n; i++){
sort(ord[i].begin(), ord[i].end());
for(int j=0; j<sz(ord[i])/2; j++){
int l = ord[i][j].second;
int r = ord[i][j + sz(ord[i])/2].second; //confusion starts here all the way to the buttom
if(l > r){
swap(l, r);
ret++;
}
v.emplace_back(l + 1, r + 1);
}
}
for(int i=1; i<=2*n; i++) bit.add(i, 1);
sort(v.begin(), v.end());
for(auto &i : v){
ret += bit.query(i.second - 1) - bit.query(i.first);
bit.add(i.first, -1);
bit.add(i.second, -1);
}
return ret;
}
int r = ord[i][j + sz(ord[i])/2].second;
我们已经在<size, idx>
的向量中对一个鞋大小的元组进行了排序,这意味着这个大小的所有负数都占据了ord[i]
的前半部分,所有正数都在后半部分。
if (l > r){
swap(l, r);
ret++;
}
在我们对大小进行排序后,每个对应对的索引可能不会先负后正。每一个都需要交换。
v.emplace_back(l + 1, r + 1);
在CCD_ 3中插入对应尺寸为i
的鞋的间隔。
for(int i=1; i<=2*n; i++) bit.add(i, 1);
sort(v.begin(), v.end());
在我们的分段总和树中,为鞋的每个索引位置添加值1。对鞋款间隔进行排序。
for(auto &i : v){
ret += bit.query(i.second - 1) - bit.query(i.first);
对于v
中的每双鞋,所需的交换数量是它们之间剩余的鞋的数量,用段的总和表示。
bit.add(i.first, -1);
bit.add(i.second, -1);
从树中移除这双鞋,这样新的分段总和就不会包括它们。我们可以这样做,因为鞋间隔是从左到右处理的,这意味着没有"鞋间隔";内部";这双鞋在外底前要经过加工。
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 一个关于在C++中重载布尔运算符的问题
- 首要问题的答案让值班员搞错了
- setlocale的C++土耳其字符串问题
- 如何重构类层次结构以避免菱形问题
- 基于boost的程序的静态链接——zlib问题
- C++格式化输出问题
- 难以理解某些人解决IOI问题的源代码