Codeforces 940F Machine Learning 带修改莫队

题目链接

题意

给定一个长度为\(n\)的数组\(a\)\(q\)个操作,操作分两种:

  1. 对于区间\([l,r]\),询问\(Mex\{c_0,c_1,c_2,⋯,c_{10^9}\}\),其中\(c_i\)表示\(i\)\([l,r]\)中的出现次数;
  2. \(a_p\)修改为\(x\).

思路

参考:http://www.cnblogs.com/PinkRabbit/p/8476664.html

\(cnt\)数组记录\(a\)数组中数字的出现次数,\(num\)数组记录\(cnt\)数组中数字的出现次数,因此\(num\)数组中第一个对应值为\(0\)的下标即为\(Mex\).

:同样的想法也可以用于维护众数的出现次数,\(num\)数组中最大的对应值不为\(0\)的下标即为众数的出现次数。

那么答案如何统计呢?
若答案为\(k\)则数字总数至少为\(1+2+\cdots+k-1=\frac{k*(k-1)}{2}\),所以每次从头开始统计答案是\(O(\sqrt n)\)的复杂度;

另外一个注意点就是\(num[0]\)的大小,也即初始为\(0\)的数字的个数,要开到离散化后的数字总数+1那么大,这是因为\(num[0]\)始终应该有值,因为要对\([0,10^9]\)的所有数统计(感谢粉兔)

Code

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 100010
using namespace std;
typedef long long LL;
int n,m,blo,temp,nn,a[maxn],t[maxn], bl[maxn], cnt[maxn<<1], num[maxn<<1], l, r, mp[maxn<<1], tot, ans[maxn],
    cnt1, cnt2, tim;
struct qnode {
    int l,r,tim,id;
    bool operator < (const qnode& nd) const {
        return bl[l]==bl[nd.l] ? (bl[r]==bl[nd.r] ? tim<nd.tim : bl[r]<bl[nd.r]) : bl[l]<bl[nd.l];
    }
}q[maxn];
struct cnode { int x, yt, ys; }c[maxn];
inline void add(int x) { --num[cnt[x]]; ++num[++cnt[x]]; }
inline void del(int x) { --num[cnt[x]]; ++num[--cnt[x]]; }
inline void cha(int x, int y) {
    if (l<=x&&x<=r) del(a[x]), add(y);
    a[x] = y;
}
void discrete() {
    sort(mp, mp+tot);
    nn=unique(mp, mp+tot)-mp;
    F2(i, 1, n) a[i]=lower_bound(mp,mp+nn,a[i])-mp+1;
    F2(i, 1, cnt2) c[i].ys=lower_bound(mp,mp+nn,c[i].ys)-mp+1, c[i].yt=lower_bound(mp,mp+nn,c[i].yt)-mp+1;
}
int main() {
    scanf("%d%d", &n, &m); blo = pow(n, 2.0/3.0);
    F2(i, 1, n) scanf("%d", &a[i]), t[i] = mp[tot++] = a[i], bl[i]=(i-1)/blo;
    F(i, 0, m) {
        int op,l,r;
        scanf("%d%d%d",&op,&l,&r);
        if (op==1) q[cnt1] = {l, r, tim, cnt1}, ++cnt1;
        else ++tim, c[++cnt2] = {l, r, t[l]}, t[l] = r, mp[tot++] = r;
    }
    discrete();
    sort(q, q+cnt1);
    r=0, l=1;
    num[0]=nn+1; tim=0;
    F(i, 0, cnt1) {
        while (tim<q[i].tim) tim++, cha(c[tim].x, c[tim].yt);
        while (tim>q[i].tim) cha(c[tim].x, c[tim].ys), --tim;
        while (r<q[i].r) add(a[++r]);
        while (l>q[i].l) add(a[--l]);
        while (r>q[i].r) del(a[r--]);
        while (l<q[i].l) del(a[l++]);
        int temp=0;
        while (num[temp]) ++temp;
        ans[q[i].id] = temp;
    }
    F(i, 0, cnt1) printf("%d\n", ans[i]);
    return 0;
}


posted @ 2018-03-01 10:43  救命怀  阅读(165)  评论(0编辑  收藏  举报