微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

CSES范围查询问题:薪资查询

如何解决CSES范围查询问题:薪资查询

我正在尝试解决此问题:https://cses.fi/problemset/task/1144/

给定一个最多包含200000个元素的数组,我的任务是处理多达200000查询,这些查询要么要求我更新数组中的单个值,要么要求我查找其中的数量。位于a和b之间的元素位于给定范围内(例如,查询将询问从索引15的元素中有多少位于[2,3]范围内。)

我目前的想法是首先对给定数组中的值使用 index压缩(因为这些值最多可以达到10^9,因此保持简单的出现数组将超出存储限制),然后保留另一个包含每个压缩数字的出现次数的数组。然后,可以使用总和分段树来完成查询的处理和更新。

但是,在尝试实施此方法时遇到了一个问题。我意识到更新单个数组值将迫使我更改压缩数组。

例如,给定数组[1,5,3,2],我将定义一个压缩函数C

C[1] = 0;
C[2] = 1;
C[3] = 2;
C[5] = 3;

然后,出现数组将为[1,1,2,1],并且处理总和查询将非常有效。但是,如果指示我 update 一个值,例如,将第三个元素更改为4,则将使所有内容失去平衡。压缩功能必须更改为

C[1] = 0;
C[2] = 1;
C[3] = 2;
C[4] = 3;
C[5] = 4;

这将迫使我重新构造我的事件数组,从而导致O(N)的更新时间。

由于N可以达到200000,尽管我认为索引压缩是正确的想法,但我目前的方法仍无法有效解决问题。有人可以用我的方法向我指出正确的方向吗?

解决方法

使用索引压缩时,您有正确的主意-好主意!由于N最多只能达到200000,因此,保持出现阵列最多将需要200000个元素作为给定数组的初始值,而不是10^9个数组索引。 / p>

根据您自己,您面临的问题是在处理查询期间遇到新值时。你是对的;这会导致发生阵列失衡并导致更新必须在O(N)时间内运行。解决此问题的方法只是对您当前的方法进行微小的修改。

要解决遇到新值的问题,我们只需确保我们从不遇到任何新值。我们可以通过在构造和段树之前读取所有查询来完成此操作。这将导致最多N + 2*Q个唯一值,或者在最坏的情况下最多产生600000,这足以构造具有问题512MB存储限制的出现数组。之后,总和分类树将能够有效地回答这些查询。

因此,最终,解决此问题的策略是输入每个唯一数字,然后构造索引压缩函数,然后使用求和分段树有效地处理求和查询。

将来,请记住,在这类查询回答问题中,在进行预计算之前读取所有输入内容可能会很有用。祝您程序顺利!

,

首先,考虑一下天真:对于每次更新,请更新阵列。对于每个查询,请扫描整个数组并收集答案。该解决方案的复杂性包括O(n)个更新和O(n)个查询。不好。

我们可以提出另一种解决方案,其时间复杂度可能会变差,但这可以提示我们最终结果是什么。始终维护源数组,但还要保留value-> frequency的哈希图。然后,当您更新时,将频率降低到旧值,然后将其增加到新值。现在,对于查询,循环遍历该查询范围的所有值,并对它们求和以得出答案。这样会导致O(1)个更新和O(r-l)个查询,因此我们的更新很棒,但查询却很糟糕。但是,如果我们可以 just 加快这些查询的速度,则可以改善此结果!输入细分树

传统上,您会在创建时一直构建一个细分树直至其叶子。但是,从名义上讲,我们希望使用一个0-10^9范围内的段树,因此,绝对不可能生成这么多的内存(这样做会超时)。但是,如果我们创建一个段树,但是对于每个节点,如果从未使用过它的子节点,则该子节点是隐式的。也就是说,如果其中没有元素,则不要创建子节点。该结构恰当地命名为隐式细分树。这里的想法是正常执行段树,只是跳过构造函数中用于初始化左右孩子的部分。现在,由于部分范围查询而需要深入研究子级时,请检查它们是否存在,如果不存在,则创建它们。否则,由于您不需要制作它们,因此假定这些节点中的值之和为0!

最终的解决方案如下:创建一个可查询最大值的细分树(如果不需要交互回答,请考虑保存并扫描查询以找到最大r值,但您不必至)。 请注意将其设为隐式细分树。每次更新后都要维护源数组,并在树上进行点更新(O(log(max value)))。查询是常规段树范围查询,因此将为O(log(max value))。在那里!

,

您可以使用基于策略的数据结构,该结构具有一些有用的方法,例如order_of_key()-返回的项目数少于给定的num。我们可以像getcnt(b + 1)-getcnt(a)这样调用两次,它给出了给定范围之间的项目数。有关更多信息-您可以参考-https://codeforces.com/blog/entry/11080以及https://gcc.gnu.org/onlinedocs/libstdc++/manual/policy_data_structures.html

经过大量研究,我发现此STL在使用基于树的结构时非常有用。

我测试了以下代码,并通过了所有测试用例。

#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
 
using namespace std;
using namespace __gnu_pbds;
 
template<class T> using cust_set = tree<
T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
cust_set<array<int,2>> freq;
 
int getcnt(int x)
{
    return freq.order_of_key({x,0});
}
int main()
{
    int n,q;
    scanf("%d%d",&n,&q);
    vector<int> emp(n);
    
    int sal;
    for(int i=0;i<n;i++)
    {
        cin >> emp[i];
        freq.insert({emp[i],i});
    }
    char c;
    int x,a,b;
    while(q--)
    {
        cin>> c;
        int ans=0;
        if(c=='?')
        {
            cin>>a>>b;
            cout << getcnt(b+1) - getcnt(a)<<"\n";
        }
        else
        {
            cin>>a>>b;
            --a;
            freq.erase({emp[a],a});
            emp[a] = b;
            freq.insert({emp[a],a});
        }
    }
    return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?