难以理解某人的源代码以解决IOI问题

雷尼尔1

这是问题的链接:https : //ioi2019.az/source/Tasks/Day1/Shoes/NGA.pdf

这是有关问题状态的简要说明

您将得到一个1n≤1e5范围内的整数n,该整数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,1: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}


当做这个问题时,我得到了错误的答案,我决定在git hub上查看某人的源代码。

这是源代码:

#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;
}

但是,我认为我不太了解这段代码。

我知道在BIT中添加查询的功能是什么,我一直困惑到底在哪里对代码进行注释。我不明白它的作用和目的。

有人可以浏览这段代码在做什么吗?或就如何正确有效地解决此问题提供任何建议(甚至可能是您的解决方案?)。谢谢。

吉拉德·巴坎(Gilad Barkan)
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);

v我们的间隔中插入一双相应尺码的鞋子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);

从树上卸下这双鞋,这样一来,新的细分金额就不会包括在内。我们可以这样做,因为鞋子间隔是从左到右进行处理的,这意味着没有一双“内”的鞋子要在外一双鞋子之前进行处理。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

难以理解MonadPlus类型类的不同实例的源代码

来自分类Dev

难以理解if语句代码

来自分类Dev

难以理解BFS代码

来自分类Dev

如何在获取页面源代码的同时解决编码问题?

来自分类Dev

难以理解解决Spoj DQuery的方法

来自分类Dev

AsyncTask源代码问题

来自分类Dev

AsyncTask源代码问题

来自分类Dev

理解(并找到)matplotlib源代码

来自分类Dev

难以理解此OCaml代码的输出

来自分类Dev

难以理解python代码的简化形式

来自分类Dev

从源代码到CentOS 6.4都难以安装PHP

来自分类Dev

Eclipse源代码级问题

来自分类Dev

Eclipse源代码级问题

来自分类Dev

Android源代码编译问题

来自分类Dev

难以理解

来自分类Dev

Spark源代码:如何理解withScope方法

来自分类Dev

用Python解决源代码中的PDE

来自分类Dev

对于简单的代码,类型约束变得巨大且难以理解

来自分类Dev

难以理解django-fluent-comments代码的工作方式

来自分类Dev

使用OpenMP难以理解代码中的某些意外行为

来自分类Dev

从Eclipse粘贴代码到Outlook的突出显示难以理解

来自分类Dev

难以理解Leetcode问题494的动态编程部分,目标总和

来自分类Dev

从源代码构建Moqui时出现的问题

来自分类Dev

河内塔,理解代码的问题

来自分类Dev

无法解决此代码的问题

来自分类Dev

无法理解Java 1.7 PopupFactory源代码

来自分类Dev

如何理解用于Imagenet预处理的TensorFlow源代码

来自分类Dev

无法理解Java 1.7 PopupFactory源代码

来自分类Dev

理解 R 中的马尔可夫链源代码