CF1834E MEX of LCM
  YdxfFsjpYokY 2023年11月02日 59 0


也许更好的阅读体验

CF1834E MEX of LCM_#define
CF1834E MEX of LCM_Code_02个数,将这CF1834E MEX of LCM_Code_02个数所有子区间的CF1834E MEX of LCM_#define_04作为一个集合CF1834E MEX of LCM_#include_05,求最小的没有出现在CF1834E MEX of LCM_#include_05中的数CF1834E MEX of LCM_#define_07
CF1834E MEX of LCM_构造_08CF1834E MEX of LCM_Code_09个数 CF1834E MEX of LCM_构造_10,所有子区间的CF1834E MEX of LCM_#define_04构成集合CF1834E MEX of LCM_#define_12,第一个未出现的数是CF1834E MEX of LCM_构造_13
CF1834E MEX of LCM_#define_14CF1834E MEX of LCM_acm_15

CF1834E MEX of LCM_#include_16
考虑已知一个区间的CF1834E MEX of LCM_#define_04,此时将区间往两边扩大CF1834E MEX of LCM_#include_18CF1834E MEX of LCM_#define_04是不降的

在知道上面之后,我们想要知道所有区间的CF1834E MEX of LCM_#define_04中最小的未出现过数,因此我们不需要一开始就知道所有的CF1834E MEX of LCM_#define_04,考虑按从小到大构造出CF1834E MEX of LCM_#define_04,又知道区间CF1834E MEX of LCM_#define_04在区间变大的过程中是一直增大的

立马就能想到用一个小根堆,最开始将每个位置上的数存进去表示以这个位置作为区间CF1834E MEX of LCM_#define_04的起点,用CF1834E MEX of LCM_构造_25表示当前考虑CF1834E MEX of LCM_构造_25是否是答案,每次取出最小的数出来看是否等于CF1834E MEX of LCM_构造_25,如果等于CF1834E MEX of LCM_构造_25那么CF1834E MEX of LCM_构造_25就不能作为答案,CF1834E MEX of LCM_构造_25需要增大,然后将堆顶的元素取出来让它的区间往右走一步再重新插进堆中,这样就能保证当第一次堆顶元素不等于CF1834E MEX of LCM_构造_25时就找到了答案

然而这样会超时,因为会有大量的重复的计算,比如CF1834E MEX of LCM_#include_32这样的序列,仅仅只是想让CF1834E MEX of LCM_构造_25变成2,就需要CF1834E MEX of LCM_#include_34复杂度不断扩大区间

考虑什么样的情况是不需要重复计算的,当有若干个区间右端点相同,左端点不同的区间的CF1834E MEX of LCM_#define_04相同时,只需要保留一个区间即可,例如,CF1834E MEX of LCM_acm_36CF1834E MEX of LCM_#define_04等于CF1834E MEX of LCM_acm_38CF1834E MEX of LCM_#define_04时,CF1834E MEX of LCM_acm_36便不需要继续往右走了,因为答案会完全和CF1834E MEX of LCM_acm_38相同

因此考虑记忆每个位置曾经出现过哪些值,当某个区间的右端点扩大后发现这个位置曾经有过区间的CF1834E MEX of LCM_#define_04和自己相同,那么就不用将这个区间加入堆中了,用CF1834E MEX of LCM_构造_43记忆这些值即可

CF1834E MEX of LCM_#define_44

#include <cstdio>
#include <queue>
#include <set>
#define ll long long
#define mp make_pair
using namespace std;
const int maxn = 3e5 + 5;
int T, n;
int x[maxn];
set <ll> now[maxn];
priority_queue < pair<ll, int> > q;
ll gcd (ll a, ll b)
{
    if (!b) return a;
    return gcd(b, a % b);
}
ll lcm (ll a, ll b){ return a * b / gcd(a, b); }
int main ()
{
    scanf("%d", &T);
while (T--) {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)    scanf("%d", &x[i]), q.push(mp(-x[i], i)), now[i].clear(), now[i].insert(x[i]);
    ll ans = 1;
    while (!q.empty() && q.top().first == -ans) {
        while (!q.empty() && q.top().first == -ans) {
            ll l = -q.top().first;
            int i = q.top().second;
            q.pop();
            if (++i <= n) {
                l = lcm(l, x[i]);
                if (now[i].find(l) == now[i].end()) q.push(mp(-l, i)), now[i].insert(l);
            }
        }
        ++ans;
    }
    while (!q.empty())	q.pop();
    printf("%lld\n", ans);
}
    return 0;
}

如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
YdxfFsjpYokY