CF 940F Machine Learning

2023-05-16

          • 传送门
          • 题目大意
          • 思路
          • 参考代码
          • Remarks

传送门
题目大意

  给你一个数组 {a1n}(n105) { a 1 ∼ n } ( n ≤ 10 5 ) ,需要进行 q(q105) q ( q ≤ 10 5 ) 次操作,支持两种操作:

  1. 查询区间 [l,r] [ l , r ] 中每个数字出现次数的 mex m e x
  2. 单点修改某一个位置的值。

   mex m e x 指的是一些数字中最小的未出现的自然数。值得注意的是,区间 [l,r] [ l , r ] 总有数字是没有出现过的,所以答案不可能为 0 0

思路

  考虑带修莫队。观察发现,原数组里的数和要修改成的数可以进行离散化操作。我们可以在 O(n53) 的时间复杂度内维护每个数的出现次数。自然我们可以在 O(1) O ( 1 ) 的复杂度内维护每个数的出现次数的出现次数,并且可以再次分块维护。

  发现,最终答案不会超过 O(2n) O ( 2 n ) ,所以分块之后求一次答案的时间复杂度为 O(n14) O ( n 1 4 ) 。算法的整体时间复杂度为 O(n53 O ( n 5 3 ,足以通过 105 10 5 的数据。

参考代码
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cassert>
#include <cctype>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <list>
#include <functional>
#define loop register int
typedef long long LL;
typedef unsigned long long ULL;
using std::cin;
using std::cout;
using std::endl;
typedef int INT_PUT;
INT_PUT readIn()
{
    INT_PUT a = 0; bool positive = true;
    char ch = getchar();
    while (!(ch == '-' || std::isdigit(ch))) ch = getchar();
    if (ch == '-') { positive = false; ch = getchar(); }
    while (std::isdigit(ch)) { a = a * 10 - (ch - '0'); ch = getchar(); }
    return positive ? -a : a;
}
void printOut(INT_PUT x)
{
    char buffer[20]; int length = 0;
    if (x < 0) putchar('-'); else x = -x;
    do buffer[length++] = -(x % 10) + '0'; while (x /= 10);
    do putchar(buffer[--length]); while (length);
    putchar('\n');
}

const int maxn = int(1e5) + 5;
int n, m;
int a[maxn];
int nModify;
struct Modify
{
    int pos, val, pre;
    void read()
    {
        pos = readIn();
        val = readIn();
    }
    inline void forward() const { a[pos] = val; }
    inline void backward() const { a[pos] = pre; }
} modifys[maxn];
int nQuery;
struct Query
{
    int l, r, t;
    int ans;
    void read()
    {
        l = readIn();
        r = readIn();
        t = nModify;
    }
} querys[maxn];

int bound;
int disc[maxn * 2];
void discretize()
{
    for (loop i = 1; i <= n; i++)
        disc[++bound] = a[i];
    for (loop i = 1; i <= nModify; i++)
        disc[++bound] = modifys[i].val;
    std::sort(disc + 1, disc + 1 + bound);
    bound = std::unique(disc + 1, disc + 1 + bound) - (disc + 1);

    for (loop i = 1; i <= n; i++)
        a[i] = std::lower_bound(disc + 1, disc + 1 + bound, a[i]) - disc;
    for (loop i = 1; i <= nModify; i++)
        modifys[i].val = std::lower_bound(disc + 1, disc + 1 + bound, modifys[i].val) - disc;
}
void initModify()
{
    for (loop i = 1; i <= nModify; i++)
    {
        Modify& t = modifys[i];
        t.pre = a[t.pos];
        t.forward();
    }
}

int blockSize;
int inBlock[maxn];

int idx[maxn];
bool comp(const int& a, const int& b)
{
    const Query& x = querys[a];
    const Query& y = querys[b];
    if (inBlock[x.l] != inBlock[y.l]) return x.l < y.l;
    if (inBlock[x.r] != inBlock[y.r]) return (inBlock[x.l] & 1) ? x.r > y.r : x.r < y.r;
    return x.t < y.t;
}
void initBlock()
{
    blockSize = std::max(1.0, std::pow(n, (double)2 / 3));
    for (loop i = 1; i <= n; i++)
        inBlock[i] = (i - 1) / blockSize + 1;

    for (loop i = 1; i <= nQuery; i++)
        idx[i] = i;
    std::sort(idx + 1, idx + 1 + nQuery, comp);
}

int times[maxn * 2];
int cntL, cntR, cntT;

int sqrtN;
int belong[maxn];
int size[maxn];
int appear[maxn];
int b[maxn];
void init()
{
    sqrtN = std::max(2.0, std::sqrt(2 * std::sqrt(n))); // 最大 2 * sqrt(n)
    for (loop i = 0; i <= n; i++)
        size[belong[i] = i / sqrtN]++;
    cntL = 1;
    cntR = 0;
    cntT = nModify;
    appear[0] = int(1e9);
    b[belong[0]]++;
}
inline void expandMex(int val)
{
    if (!(appear[val]++))
        b[belong[val]]++;
}
inline void shrinkMex(int val)
{
    if (!(--appear[val]))
        b[belong[val]]--;
}
int getAns()
{
    loop ans = 0;
    loop ib = 0;
    while (b[ib] == size[ib])
    {
        ans += sqrtN;
        ib++;
    }
    while (appear[ans])
        ans++;
    return ans;
}

inline void expand(int pos)
{
    int& t = times[a[pos]];
    shrinkMex(t);
    expandMex(++t);
}
inline void shrink(int pos)
{
    int& t = times[a[pos]];
    shrinkMex(t);
    expandMex(--t);
}
inline void expandT(int t)
{
    const Modify& T = modifys[t];
    if (cntL <= T.pos && T.pos <= cntR)
    {
        shrinkMex(times[a[T.pos]]);
        expandMex(--times[a[T.pos]]);
        T.forward();
        shrinkMex(times[a[T.pos]]);
        expandMex(++times[a[T.pos]]);
    }
    else
        T.forward();
}
inline void shrinkT(int t)
{
    const Modify& T = modifys[t];
    if (cntL <= T.pos && T.pos <= cntR)
    {
        shrinkMex(times[a[T.pos]]);
        expandMex(--times[a[T.pos]]);
        T.backward();
        shrinkMex(times[a[T.pos]]);
        expandMex(++times[a[T.pos]]);
    }
    else
        T.backward();
}

void solve()
{
    initBlock();
    init();
    for (int i = 1; i <= nQuery; i++)
    {
        Query& q = querys[idx[i]];

        while (cntL > q.l) expand(--cntL);
        while (cntR < q.r) expand(++cntR);
        while (cntL < q.l) shrink(cntL++);
        while (cntR > q.r) shrink(cntR--);
        while (cntT < q.t) expandT(++cntT);
        while (cntT > q.t) shrinkT(cntT--);

        q.ans = getAns();
    }

    for (int i = 1; i <= nQuery; i++)
        printOut(querys[i].ans);
}

void run()
{
    n = readIn();
    m = readIn();
    for (int i = 1; i <= n; i++)
        a[i] = readIn();
    while (m--)
    {
        int type = readIn();
        if (type == 1)
            querys[++nQuery].read();
        else
            modifys[++nModify].read();
    }
    discretize();
    initModify();

    solve();
}

int main()
{
    run();
    return 0;
}
Remarks

From murugappan_s

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CF 940F Machine Learning 的相关文章

随机推荐

  • 2023 New Year‘s Resolution

    This Is Game 2023 New Year 39 s Resolution My 2022 ended with a day of game I am convinced that I am not to blame becaus
  • 补录:2018 和 2019 New Year‘s Resolution

    前言 xff1a 吉光片羽 xff0c 以飨读者 2018 New Year 39 s Resolution One year and a half ago I felt that life in 2020 would be quite d
  • 原博文地址

    由于账号问题 xff0c 现更改为这个账号 xff0c 以下为原博文地址 使用WH MOUSE LL钩子来判断按键是否是mouse event模拟的 http blog csdn net qq 26140973 article detail
  • [NOI 2003] 文本编辑器 Splay 维护序列 / 块状链表

    传送门 xff08 JZOJ xff09 xff08 第一道全国决赛题 xff09 解法 1 xff1a 使用 Splay 维护 不管怎么说 xff0c 总和刚刚学过的迎合上了 这道题可以直接上 Splay 维护线性序列 xff0c 光标位
  • 一次macOS的升级填坑(macOS Catalina - macOS Monterey)

    目录 小序一 升级前操作二 升级中三 问题填坑1 像我一样长时间卡在一个进度条怎么办2 在更新途中重启过电脑 xff08 完整流程填坑 xff09 3 安装之后不能开机 xff0c 如何紧急拷贝资料4 安装不成功 xff0c 如何重新安装系
  • CF 713C Sonya and Problem Wihtout a Legend

    文章目录 传送门题目大意正解通过维护关键点来维护信息参考代码 传送门 题目大意 给定一个长度为 n n 3000
  • Luogu 3642 [APIO 2016] 烟火表演

    传送门引例 xff08 上一道题 xff09 凸函数一开始的思路正解参考代码总结 传送门 引例 xff08 上一道题 xff09 凸函数 回忆我们上一道题是怎么做的 我们维护的东西的实质是一个 xff08 下 xff09 凸函数 由于我们的
  • Luogu 3631 [APIO 2011] 方格染色

    传送门思路参考代码细节 传送门 思路 很不错的一道题 xff0c 用到的东西不深 xff0c 但是要想到确实需要一定思维 一开始我想的是动态规划 xff0c 发现如果要设状态需要知道一个格子左边 xff0c 上边和左上边三个格子的状态 然后
  • Luogu 3632 [APIO 2011] 寻路

    传送门正解参考代码 传送门 正解 暴力连边跑最短路就好了 xff0c 只不过代码太长太难写啦 xff01 参考代码 span class hljs preprocessor include lt cstdio gt span span cl
  • Luogu 3634 [APIO 2012] 守卫

    传送门思路正解参考代码 传送门 思路 感觉自己越来越笨了 首先 xff0c 很明显这道题需要把没有看到忍者的区间给删去 xff0c 可以用前缀和 O n O n 处理 xff0c 然后对没有删去的地方重新标号 重新标号时 xff0c 需要对
  • Luogu 1552 [APIO 2012] 派遣

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 题读错了两次 xff0c 一开始读成了一个一般的背包 xff0c 然后读成了一个价值和花费相同的背包 xff0c 最后才发现原来是一个价值为 1
  • 贪玩 CF 之旅

    文章目录 CF 7D Palindrome Degree http codeforces com problemset problem 7 D 题解 CF 713C Sonya and Problem Wihtout a Legend ht
  • Luogu 3638 [APIO 2013] 机器人

    传送门思路正解参考代码关于 SPFA 传送门 思路 n n 这么小 会不会是搜索题 稍有经验的我直接否定了这个结论 仔细读题并分析样例 发现原来一个位置可以有多个机器人 且机器人行走的时候无视其它机器人 那这个就是一张图啊 可以将这张图预处
  • Luogu 3647 [APIO 2014] 连珠线

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 又看错题了 题目中说一个新的珠子和一个已经添加的珠子连接起来 xff0c 我没有看到 xff0c 然后就凉了 立个 flag xff1a 已经连续看错五题了 xff0c
  • 【转】mingw64的安装方法

    转自 xff1a http write blog csdn net postlist mingw64的安装方法 1 下载ming w64 http sourceforge net projects mingw w64 files or x8
  • Luogu 3645 [APIO 2015] 雅加达的摩天楼

    传送门思路正解参考代码Update 传送门 思路 唉 xff0c 我太弱了 xff0c 我都看出来要分块了 xff0c 就是做不来 不过终于把题读对了 先来看子任务三怎么做 显然可以有一个 O m 2 O m 2
  • Luogu 3644 [APIO 2015] 八邻旁之桥

    传送门思路当 k 61 2 时参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 题也做不来 很明显这道题先要把不过河的人排除了 xff0c 剩下的都是要过河的 当 k 61 1 k 61 1 时 xff0
  • Luogu 3646 [APIO 2015] 巴厘岛的雕塑

    传送门总结 APIO 2015思路参考代码总结 传送门 总结 APIO 2015 争取今天做完一套 QAQ T1 我最多之能想到从高位向低位做 xff0c 然后就完全不会了 xff1b T2 我想到了分情况讨论 xff0c 但是没有建图成功
  • UOJ 2016 [APIO 2016] Gap

    传送门思路参考代码交互题 交互题大致形式Windows 平台下 xff08 Dev C 43 43 xff09 Ubuntu 平台下 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 题也做不来 这道题简直就是利用
  • CF 940F Machine Learning

    传送门题目大意思路参考代码Remarks 传送门 题目大意 给你一个数组 a 1 n n 10 5 a 1 n