• Machine Learning CodeForces


    题解原文地址:https://www.cnblogs.com/lujiaju6555/p/8468709.html

    给数组a,有两种操作,1 l r查询[l,r]中每个数出现次数的mex,注意是出现次数,mex是最小未出现的自然数,2 x y将a[x]修改为y。

    题解:带修改莫队可以解决此题。带修改莫队不会的同学可以先去做下BZOJ2120,然后mex+莫队可以参考BZOJ3585。带修改莫队就是加入了第三关键字time,然后按(左端点所在块,右端点所在块,时间)排序,其中时间指的是在第几次修改操作后。注意修改时要记下原来的数,以便还原回去。维护mex可以对权值分块,如果某块中数的个数==R-L+1,那么这块所有数都出现了,否则暴力扫,我有个同学直接暴力维护也过了。。。

    #include <bits/stdc++.h>
    #define MOD 2018
    #define LL long long
    #define ULL unsigned long long
    #define Pair pair<int, int>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define _  ios_base::sync_with_stdio(0),cin.tie(0)
    //freopen("1.txt", "r", stdin);
    using namespace std;
    const int maxn = 200005, INF = 0x7fffffff;
    int n, m, pos[maxn], s[maxn], c[maxn], all[maxn], t[maxn], cnt[maxn];
    int qsz, csz;
    struct node
    {
        int l, r, t, res, id;
    }Node[maxn];
    
    void add_n(int l, int r, int t, int id)
    {
        Node[id].l = l;
        Node[id].r = r;
        Node[id].t = t;
        Node[id].id = id;
    }
    
    struct change
    {
        int pos, New, Old;
    }Cha[maxn];
    
    void add_c(int pos, int New, int Old, int ans)
    {
        Cha[ans].pos = pos;
        Cha[ans].New = New;
        Cha[ans].Old = Old;
    }
    
    bool cmp(node a, node b)
    {
        if(pos[a.l] == pos[b.l])
        {
            if(pos[a.r] == pos[b.r])
                return a.t < b.t;
            return pos[a.r] < pos[b.r];
        }
        return pos[a.l] < pos[b.l];
    }
    
    bool cmp_id(node a, node b)
    {
        return a.id < b.id;
    }
    
    int update(int val, int d)
    {
        if(s[val] > 0) cnt[s[val]]--;    //s是记录val 出现的次数  cnt标记这个次数是否出现  因为有多个数 可能有些数出现的次数相同 所有用++即可
        s[val] += d;                     //因为当前数val的次数改变 所以 如果未改变时的val的次数 给cnt贡献了1个的话 要先减去 再更新s[val] 再更新cnt[s[val]]
        if(s[val] > 0) cnt[s[val]]++;
    }
    int L=1, R=0, T=0;
    int go(int idx, int val)
    {
        if(L <= idx && idx <= R)  //如果 当前时间内 修改的位置在当前区间 则先删去上一次在这个位置更新的值 再加上本次在这个位置更新的值
        {
            update(c[idx], -1);
            update(val, 1);
        }
        c[idx] = val;     //更新
    }
    
    
    int main()
    {
        qsz = csz = 0;
        int tot = 0;
        scanf("%d%d", &n, &m);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&c[i]);
            t[i] = c[i];
            all[++tot] = c[i];
        }
        int block=pow(n,2.0/3);
        for(int i=1; i<=n; i++)
            pos[i] = (i-1)/block + 1;
        for(int i=1; i<=m; i++)
        {
            int op, l, r;
            scanf("%d%d%d", &op, &l, &r);
            if(op == 1)
            {
                add_n(l, r, csz, ++qsz);
            }
            else
            {
                add_c(l, r, t[l], ++csz);
                t[l] = r;
                all[++tot] = r;
            }
        }
        sort(all+1, all+tot+1);
        tot = unique(all+1, all+tot+1) - (all + 1);
        for(int i=1; i<=n; i++)
            c[i] = lower_bound(all+1, all+tot+1, c[i]) - all;
        for(int i=1; i<=csz; i++)
        {
            Cha[i].New = lower_bound(all+1, all+tot+1, Cha[i].New) - all;
            Cha[i].Old = lower_bound(all+1, all+tot+1, Cha[i].Old) - all;
        }
        sort(Node+1, Node+qsz+1, cmp);
        for(int i=1; i<=qsz; i++)
        {
    //        for(; T < Node[i].t; T++)
    //            go(Cha[T+1].pos, Cha[T+1].New);
    //        for(; T > Node[i].t; T--)
    //            go(Cha[T].pos, Cha[T].Old);
            for(; R < Node[i].r; R++)
                update(c[R+1], 1);
            for(; R > Node[i].r; R--)
                update(c[R], -1);
            for(; L < Node[i].l; L++)
                update(c[L], -1);
            for(; L > Node[i].l; L--)
                update(c[L-1], 1);
            for(; T < Node[i].t; T++)       //遍历在询问当前区间时 的 时间之前的修改
                go(Cha[T+1].pos, Cha[T+1].New);
            for(; T > Node[i].t; T--)
                go(Cha[T].pos, Cha[T].Old);
    
            for(int j=1; ; j++)
                if(!cnt[j])
                {
                    Node[i].res = j;
                    break;
                }
         //   cout<< Node[i].res <<endl;
        }
        sort(Node+1, Node+qsz+1, cmp_id);
        for(int i=1; i<=qsz; i++)
            cout<< Node[i].res <<endl;
    
        return 0;
    }
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    NET微信公众号开发环境搭建(一)-了解微信由来
    JS:复制内容到剪贴板(无插件,兼容所有浏览器)
    js 压缩上传的图片方法(默认上传的是file文件)
    vue封装组件调用时绑定click事件
    vue cli3 区分开发环境,测试环境,正式环境(二)
    vue 动态修改网页标题 title
    vue移动端适配(px转vw)postcss-px-to-viewport配置
    veu创建项目,自定义配置
    vue cli3配置开发环境、测试环境、生产(线上)环境(一)
    vue封装axios
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/9346960.html
Copyright © 2020-2023  润新知