打破2组中1到n个数的排列[关闭]

Posted

技术标签:

【中文标题】打破2组中1到n个数的排列[关闭]【英文标题】:breaking permutation of 1 to n number in 2 set [closed] 【发布时间】:2020-04-27 20:18:44 【问题描述】:

问题链接:https://codeforces.com/contest/1295/problem/E

这个问题表明存在 1 到 n 个数字的排列,这样每个数字只出现一次

例如。对于 n = 3,p = [ 1,2,3] 或 [2,1,3]。

现在对于 p 中的每个排列,排列 p 的第 ith 个元素都有一个成本 ci。每当我将 ith 元素从一组移到另一组时,我都必须支付 ci

因此,问题要求我在任意位置 k 处打破两组排列,使得 1

例如

p = [3,1,2] c = [7,1,4]。

set1 = [3,1] & set2 = [2]。 所以现在我们可以以 4 的最低成本将 2 从 set2 发送到 set1。

更多示例请参考问题。链接在上面。

我的方法:

对于任何 k 我们需要在 set1 中有 1 到 k 个元素并在 set2 中休息。 所以让我们从i = 1 开始,继续前进直到i = n-1 && 在我维护pfx ans 的每个位置。 要计算每个pos = i 的pfx 数组,如果p[i] > i,那么我们需要添加成本,因为我们必须将元素转移到set2,如果它小于i,那么我们需要减去因为我们想要之前,所以我们的总成本中有它。但现在我们不希望它成为我们的成本,因为我们拥有价值。同样,如果我有 cur 值,我也计算了每个位置。

这是我的代码。它通过了许多测试用例,但一直在第 10 位失败。无法理解原因。

请帮忙。

#include <bits/stdc++.h>

#define ll unsigned long long
#define pii pair<int,int>

using namespace std;

int main(void)

    ll n , ans, prc3=0;
    cin>>n;
    vector<ll> p(n+1),a(n+1);

    for(ll i=1; i<=n; i++) cin>>p[i];
    for(ll i=1; i<=n; i++) cin>>a[p[i]], prc3 += a[p[i]];

    ll prc1=0, prc2=0;
    ll ans1=INT_MAX, ans2=INT_MAX, ans3=INT_MAX;

    vector<bool> vst(n+1,false);

    for(ll i=1; i<n; i++)
    
        if(p[i]>i)
        
            prc1 += a[p[i]];
        
        else if(p[i]<i)
        
            prc1 -= a[p[i]];
        

        if(vst[i])
        
            prc1 -= a[i];
        

        vst[p[i]] = true;

        if(!vst[i])
        
            prc1 += a[i];
        

        ans1 = min(ans1,prc1);

        prc2 += a[p[i]];

        ans2 = min(ans2,prc2);

        prc3 -= a[p[i]];

        ans3 = min(ans3,prc3);


    

    ans = min(ans1,ans2);
    ans = min(ans,ans3);

    cout << ans << endl;

    return 0;


【问题讨论】:

如果有的话,应该把第十个测试用例的输入添加到问题中。 顺便说一句,将#include &lt;bits/stdc++.h&gt;using namespace std; 结合起来要非常小心,这可能是许多神奇神秘错误的来源。 您在这里主要与专业开发人员打交道,而不是与竞争激烈的程序员打交道,因此如果您希望代码可读,则需要删除程序的前四行等癌症代码. @user4581301 不,这永远不会导致问题,第 10 种情况有超过 18000 个元素,百日咳值为 1e9 通过将[] 运算符替换为at 方法或通过valgrind 运行第十个测试用例,查看是否有任何向量超出范围。 【参考方案1】:

我不确定您的代码到底想做什么,但是从我自己解决这个问题并最终阅读editorial 来看,在我看来,在约束范围内实现解决方案需要树数据结构。

据我了解,我们保留了一个变量k,它代表左侧的最高数字。我们从 1 开始 k,然后迭代到 n。同时,我们保留一棵树,其中每个键i 指向从位置i 开始创建当前k 分区的成本。

当我们增加k 时,所有在起始列表中大于或等于k 位置的分区起始位置is 将不需要移动该元素,因此我们更新所有那些@ 987654331@s,使用树在O(log n) 时间内从每一个中减去A[p[k]];并更新所有指向小于k 的分区起始位置的is,将移动的成本添加到每个位置。我们在每次迭代中取最低成本。

据我所知,O(log n) 时间段的更新需要树形数据结构。

【讨论】:

以上是关于打破2组中1到n个数的排列[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

将自然数从小到大排列,试求: 1、 前10个数的和 2、前100个数的和 3、前n个数的和

C ++比较2个数组中的整数?

TODO:排列组合问题:n个数中取m个

2个数组 如何判断2个数组中不同的元素

找元组中差值最大最小个数

面试题